Implement serde for Value; Rework comment parsing
This commit is contained in:
parent
d37c618ead
commit
859d8db384
@ -65,11 +65,7 @@ impl AbstractNode for Assignment {
|
|||||||
..
|
..
|
||||||
} = function_type
|
} = function_type
|
||||||
{
|
{
|
||||||
if let Type::Generic {
|
if let Type::Generic { identifier, .. } = *return_type {
|
||||||
identifier,
|
|
||||||
concrete_type,
|
|
||||||
} = *return_type
|
|
||||||
{
|
|
||||||
let returned_parameter = type_parameters
|
let returned_parameter = type_parameters
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.find(|parameter| parameter == &identifier);
|
.find(|parameter| parameter == &identifier);
|
||||||
|
@ -24,7 +24,7 @@ impl<'src> Display for Token<'src> {
|
|||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Token::Boolean(boolean) => write!(f, "{boolean}"),
|
Token::Boolean(boolean) => write!(f, "{boolean}"),
|
||||||
Token::Comment(comment) => write!(f, "# {comment}"),
|
Token::Comment(comment) => write!(f, "// {comment}"),
|
||||||
Token::Integer(integer) => write!(f, "{integer}"),
|
Token::Integer(integer) => write!(f, "{integer}"),
|
||||||
Token::Float(float) => write!(f, "{float}"),
|
Token::Float(float) => write!(f, "{float}"),
|
||||||
Token::String(string) => write!(f, "{string}"),
|
Token::String(string) => write!(f, "{string}"),
|
||||||
|
@ -204,96 +204,109 @@ impl InterpreterError {
|
|||||||
|
|
||||||
for error in self.errors {
|
for error in self.errors {
|
||||||
let (mut builder, validation_error) = match error {
|
let (mut builder, validation_error) = match error {
|
||||||
DustError::Lex {
|
DustError::Lex {
|
||||||
expected,
|
expected,
|
||||||
span,
|
span,
|
||||||
reason,
|
reason,
|
||||||
} => {
|
} => {
|
||||||
let description = if expected.is_empty() {
|
let description = if expected.is_empty() {
|
||||||
"Invalid character.".to_string()
|
"Invalid character.".to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("Expected {expected}.")
|
format!("Expected {expected}.")
|
||||||
};
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
Report::build(
|
Report::build(
|
||||||
ReportKind::Custom("Lexing Error", Color::Yellow),
|
ReportKind::Custom("Lexing Error", Color::Yellow),
|
||||||
self.source_id.clone(),
|
self.source_id.clone(),
|
||||||
span.1,
|
span.1,
|
||||||
|
)
|
||||||
|
.with_message(description)
|
||||||
|
.with_label(
|
||||||
|
Label::new((self.source_id.clone(), span.0..span.1))
|
||||||
|
.with_message(reason)
|
||||||
|
.with_color(Color::Red),
|
||||||
|
),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.with_message(description)
|
}
|
||||||
.with_label(
|
DustError::Parse {
|
||||||
Label::new((self.source_id.clone(), span.0..span.1))
|
expected,
|
||||||
.with_message(reason)
|
span,
|
||||||
.with_color(Color::Red),
|
found,
|
||||||
),
|
} => {
|
||||||
None,
|
let description = if expected.is_empty() {
|
||||||
)
|
"Invalid token.".to_string()
|
||||||
}
|
} else {
|
||||||
DustError::Parse {
|
format!("Expected {expected}.")
|
||||||
expected,
|
};
|
||||||
span,
|
let found = found
|
||||||
found,
|
.unwrap_or_else(|| "End of input".to_string())
|
||||||
} => {
|
.fg(token_color);
|
||||||
let description = if expected.is_empty() {
|
|
||||||
"Invalid token.".to_string()
|
|
||||||
} else {
|
|
||||||
format!("Expected {expected}.")
|
|
||||||
};
|
|
||||||
let found = found.unwrap_or_else(|| "End of input".to_string()).fg(token_color);
|
|
||||||
|
|
||||||
(
|
(
|
||||||
Report::build(
|
Report::build(
|
||||||
ReportKind::Custom("Parsing Error", Color::Yellow),
|
ReportKind::Custom("Parsing Error", Color::Yellow),
|
||||||
self.source_id.clone(),
|
self.source_id.clone(),
|
||||||
span.1,
|
span.1,
|
||||||
|
)
|
||||||
|
.with_message(description)
|
||||||
|
.with_label(
|
||||||
|
Label::new((self.source_id.clone(), span.0..span.1))
|
||||||
|
.with_message(format!("{found} is not valid in this position."))
|
||||||
|
.with_color(Color::Red),
|
||||||
|
),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.with_message(description)
|
}
|
||||||
.with_label(
|
DustError::Validation { error, position } => (
|
||||||
Label::new((self.source_id.clone(), span.0..span.1))
|
Report::build(
|
||||||
.with_message(format!("{found} is not valid in this position."))
|
ReportKind::Custom("Validation Error", Color::Magenta),
|
||||||
.with_color(Color::Red),
|
self.source_id.clone(),
|
||||||
|
position.1,
|
||||||
|
)
|
||||||
|
.with_message("The syntax is valid but this code would cause an error.")
|
||||||
|
.with_note(
|
||||||
|
"This error was detected by the interpreter before running the code.",
|
||||||
),
|
),
|
||||||
None,
|
Some(error),
|
||||||
)
|
|
||||||
}
|
|
||||||
DustError::Validation { error, position } => (
|
|
||||||
Report::build(
|
|
||||||
ReportKind::Custom("Validation Error", Color::Magenta),
|
|
||||||
self.source_id.clone(),
|
|
||||||
position.1,
|
|
||||||
)
|
|
||||||
.with_message("The syntax is valid but this code would cause an error.")
|
|
||||||
.with_note("This error was detected by the interpreter before running the code."),
|
|
||||||
Some(error),
|
|
||||||
),
|
|
||||||
DustError::Runtime { error, position } => (
|
|
||||||
Report::build(
|
|
||||||
ReportKind::Custom("Runtime Error", Color::Red),
|
|
||||||
self.source_id.clone(),
|
|
||||||
position.1,
|
|
||||||
)
|
|
||||||
.with_message("An error occured that forced the program to exit.")
|
|
||||||
.with_note(
|
|
||||||
"There may be unexpected side-effects because the program could not finish.",
|
|
||||||
)
|
|
||||||
.with_help(
|
|
||||||
"This is the interpreter's fault. Please submit a bug with this error message.",
|
|
||||||
)
|
|
||||||
.with_label(
|
|
||||||
Label::new((self.source_id.clone(), position.0..position.1)).with_message("Runtime error occured here.")
|
|
||||||
),
|
),
|
||||||
if let RuntimeError::ValidationFailure(validation_error) = error {
|
DustError::Runtime { error, position } => {
|
||||||
Some(validation_error)
|
let error_message = match &error {
|
||||||
} else {
|
RuntimeError::Io(_) => todo!(),
|
||||||
None
|
RuntimeError::RwLockPoison(_) => todo!(),
|
||||||
},
|
RuntimeError::ValidationFailure(_) => todo!(),
|
||||||
),
|
RuntimeError::SerdeJson(serde_json_error) => serde_json_error.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
(
|
||||||
|
Report::build(
|
||||||
|
ReportKind::Custom("Runtime Error", Color::Red),
|
||||||
|
self.source_id.clone(),
|
||||||
|
position.1,
|
||||||
|
)
|
||||||
|
.with_message("An error occured that forced the program to exit.")
|
||||||
|
.with_note(
|
||||||
|
"There may be unexpected side-effects because the program could not finish.",
|
||||||
|
)
|
||||||
|
.with_help(
|
||||||
|
"This is the interpreter's fault. Please submit a bug with this error message.",
|
||||||
|
)
|
||||||
|
.with_label(
|
||||||
|
Label::new((self.source_id.clone(), position.0..position.1)).with_message(error_message)
|
||||||
|
),
|
||||||
|
|
||||||
|
if let RuntimeError::ValidationFailure(validation_error) = error {
|
||||||
|
Some(validation_error)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(validation_error) = validation_error {
|
if let Some(validation_error) = validation_error {
|
||||||
match validation_error {
|
match validation_error {
|
||||||
|
|
||||||
ValidationError::CannotAssignToNone(postion) => {
|
ValidationError::CannotAssignToNone(postion) => {
|
||||||
builder.add_label(
|
builder.add_label(
|
||||||
Label::new((self.source_id.clone(), postion.0..postion.1))
|
Label::new((self.source_id.clone(), postion.0..postion.1))
|
||||||
|
@ -33,6 +33,9 @@ pub fn parse<'src>(
|
|||||||
pub fn parser<'src>(
|
pub fn parser<'src>(
|
||||||
allow_built_ins: bool,
|
allow_built_ins: bool,
|
||||||
) -> impl Parser<'src, ParserInput<'src>, Vec<Statement>, ParserExtra<'src>> {
|
) -> impl Parser<'src, ParserInput<'src>, Vec<Statement>, ParserExtra<'src>> {
|
||||||
|
let comment = select_ref! {
|
||||||
|
Token::Comment(_) => {}
|
||||||
|
};
|
||||||
let identifiers: RefCell<HashMap<&str, Identifier>> = RefCell::new(HashMap::new());
|
let identifiers: RefCell<HashMap<&str, Identifier>> = RefCell::new(HashMap::new());
|
||||||
let identifier = select! {
|
let identifier = select! {
|
||||||
Token::Identifier(text) => {
|
Token::Identifier(text) => {
|
||||||
@ -527,6 +530,7 @@ pub fn parser<'src>(
|
|||||||
basic_value,
|
basic_value,
|
||||||
identifier_expression,
|
identifier_expression,
|
||||||
))
|
))
|
||||||
|
// .delimited_by(comment.clone().or_not(), comment.or_not())
|
||||||
});
|
});
|
||||||
|
|
||||||
let expression_statement = expression
|
let expression_statement = expression
|
||||||
@ -621,27 +625,24 @@ pub fn parser<'src>(
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
choice((
|
comment
|
||||||
async_block,
|
.repeated()
|
||||||
if_else,
|
.or_not()
|
||||||
assignment,
|
.ignore_then(choice((
|
||||||
expression_statement,
|
async_block,
|
||||||
r#break,
|
if_else,
|
||||||
block_statement,
|
assignment,
|
||||||
r#loop,
|
expression_statement,
|
||||||
r#while,
|
r#break,
|
||||||
type_assignment,
|
block_statement,
|
||||||
))
|
r#loop,
|
||||||
.then_ignore(just(Token::Control(Control::Semicolon)).or_not())
|
r#while,
|
||||||
|
type_assignment,
|
||||||
|
)))
|
||||||
|
.then_ignore(just(Token::Control(Control::Semicolon)).or_not())
|
||||||
});
|
});
|
||||||
|
|
||||||
select_ref! {
|
statement.repeated().collect()
|
||||||
Token::Comment(_) => {}
|
|
||||||
}
|
|
||||||
.or_not()
|
|
||||||
.ignore_then(statement)
|
|
||||||
.repeated()
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -6,7 +6,11 @@ use std::{
|
|||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{
|
||||||
|
de::Visitor,
|
||||||
|
ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeTuple},
|
||||||
|
Deserialize, Deserializer, Serialize,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{AbstractNode, Block, Evaluation, Type, WithPosition},
|
abstract_tree::{AbstractNode, Block, Evaluation, Type, WithPosition},
|
||||||
@ -184,20 +188,312 @@ impl Ord for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for Value {
|
impl Serialize for Value {
|
||||||
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
match self.0.as_ref() {
|
||||||
|
ValueInner::Boolean(boolean) => serializer.serialize_bool(*boolean),
|
||||||
|
ValueInner::Float(float) => serializer.serialize_f64(*float),
|
||||||
|
ValueInner::Function(Function {
|
||||||
|
type_parameters,
|
||||||
|
value_parameters,
|
||||||
|
return_type,
|
||||||
|
body,
|
||||||
|
}) => {
|
||||||
|
let mut struct_ser = serializer.serialize_struct("Function", 4)?;
|
||||||
|
|
||||||
|
struct_ser.serialize_field("type_parameters", type_parameters)?;
|
||||||
|
struct_ser.serialize_field("value_parameters", value_parameters)?;
|
||||||
|
struct_ser.serialize_field("return_type", return_type)?;
|
||||||
|
struct_ser.serialize_field("body", body)?;
|
||||||
|
|
||||||
|
struct_ser.end()
|
||||||
|
}
|
||||||
|
ValueInner::Integer(integer) => serializer.serialize_i64(*integer),
|
||||||
|
ValueInner::List(list) => {
|
||||||
|
let mut list_ser = serializer.serialize_seq(Some(list.len()))?;
|
||||||
|
|
||||||
|
for item in list {
|
||||||
|
list_ser.serialize_element(&item.node)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_ser.end()
|
||||||
|
}
|
||||||
|
ValueInner::Map(map) => {
|
||||||
|
let mut map_ser = serializer.serialize_map(Some(map.len()))?;
|
||||||
|
|
||||||
|
for (identifier, value) in map {
|
||||||
|
map_ser.serialize_entry(identifier, value)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
map_ser.end()
|
||||||
|
}
|
||||||
|
ValueInner::Range(range) => {
|
||||||
|
let mut tuple_ser = serializer.serialize_tuple(2)?;
|
||||||
|
|
||||||
|
tuple_ser.serialize_element(&range.start)?;
|
||||||
|
tuple_ser.serialize_element(&range.end)?;
|
||||||
|
|
||||||
|
tuple_ser.end()
|
||||||
|
}
|
||||||
|
ValueInner::String(string) => serializer.serialize_str(string),
|
||||||
|
ValueInner::Structure { name, fields } => {
|
||||||
|
let mut struct_ser = serializer.serialize_struct("Structure", 2)?;
|
||||||
|
|
||||||
|
struct_ser.serialize_field("name", name)?;
|
||||||
|
struct_ser.serialize_field("fields", fields)?;
|
||||||
|
|
||||||
|
struct_ser.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ValueVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for ValueVisitor {
|
||||||
|
type Value = Value;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter
|
||||||
|
.write_str("a boolean, float, function, integer, list, map, range, string or structure")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Err(serde::de::Error::invalid_type(
|
||||||
|
serde::de::Unexpected::Bool(v),
|
||||||
|
&self,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_i64(v as i64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_i64(v as i64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_i64(v as i64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Ok(Value::integer(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
{
|
{
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_u64(v as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_u64(v as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_u64(v as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Ok(Value::integer(v as i64))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_f64(v as f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Err(serde::de::Error::invalid_type(
|
||||||
|
serde::de::Unexpected::Float(v),
|
||||||
|
&self,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_str(v.encode_utf8(&mut [0u8; 4]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Err(serde::de::Error::invalid_type(
|
||||||
|
serde::de::Unexpected::Str(v),
|
||||||
|
&self,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_str(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_str(&v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Err(serde::de::Error::invalid_type(
|
||||||
|
serde::de::Unexpected::Bytes(v),
|
||||||
|
&self,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_bytes(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_bytes(&v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_none<E>(self) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Err(serde::de::Error::invalid_type(
|
||||||
|
serde::de::Unexpected::Option,
|
||||||
|
&self,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let _ = deserializer;
|
||||||
|
Err(serde::de::Error::invalid_type(
|
||||||
|
serde::de::Unexpected::Option,
|
||||||
|
&self,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Err(serde::de::Error::invalid_type(
|
||||||
|
serde::de::Unexpected::Unit,
|
||||||
|
&self,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let _ = deserializer;
|
||||||
|
Err(serde::de::Error::invalid_type(
|
||||||
|
serde::de::Unexpected::NewtypeStruct,
|
||||||
|
&self,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: serde::de::SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
let _ = seq;
|
||||||
|
Err(serde::de::Error::invalid_type(
|
||||||
|
serde::de::Unexpected::Seq,
|
||||||
|
&self,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: serde::de::MapAccess<'de>,
|
||||||
|
{
|
||||||
|
let _ = map;
|
||||||
|
Err(serde::de::Error::invalid_type(
|
||||||
|
serde::de::Unexpected::Map,
|
||||||
|
&self,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: serde::de::EnumAccess<'de>,
|
||||||
|
{
|
||||||
|
let _ = data;
|
||||||
|
Err(serde::de::Error::invalid_type(
|
||||||
|
serde::de::Unexpected::Enum,
|
||||||
|
&self,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Value {
|
impl<'de> Deserialize<'de> for Value {
|
||||||
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
D: serde::Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
todo!()
|
deserializer.deserialize_any(ValueVisitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
|
// This function returns its argument.
|
||||||
foo = fn |T| (x: T) -> T { x }
|
foo = fn |T| (x: T) -> T { x }
|
||||||
bar: str = foo::(str)::("hi")
|
|
||||||
|
// Use turbofish to supply type information.
|
||||||
|
bar = foo::(str)::("hi")
|
||||||
|
|
||||||
|
// Use type annotation
|
||||||
baz: str = foo("hi")
|
baz: str = foo("hi")
|
||||||
|
|
||||||
|
// The `json.parse` function takes a string and returns the specified type
|
||||||
|
|
||||||
|
// Use turbofish
|
||||||
x = json.parse::(int)::("1")
|
x = json.parse::(int)::("1")
|
||||||
|
|
||||||
|
// Use type annotation
|
||||||
x: int = json.parse("1")
|
x: int = json.parse("1")
|
||||||
|
Loading…
Reference in New Issue
Block a user