This commit is contained in:
Robin Appelman 2020-12-02 00:16:45 +01:00
commit 3184e19b95
2 changed files with 75 additions and 6 deletions

View file

@ -12,6 +12,17 @@ use std::num::{ParseFloatError, ParseIntError};
use std::str::ParseBoolError; use std::str::ParseBoolError;
use thiserror::Error; use thiserror::Error;
/// An error and related source span, will print out the problematic code fragment and error on `Display`
///
/// ## Example
/// . |
/// 2 | [
/// 3 | "broken"
/// 4 | "array"
/// | ^^^^^^^^ Unexpected token, found Some(LiteralString) expected one of [SquareClose, Comma, Arrow]
/// 5 | ]
/// 6 |
///
#[derive(Debug)] #[derive(Debug)]
pub struct SpannedError<'a, T: Error + Debug> { pub struct SpannedError<'a, T: Error + Debug> {
span: Span, span: Span,

View file

@ -19,6 +19,28 @@ pub enum Value {
Array(HashMap<Key, Value>), Array(HashMap<Key, Value>),
} }
/// A php value, can be either a bool, int, float, string or array
/// note that in php all arrays are associative and thus represented by a map in rust.
///
/// You can convert a `Value` into a regular rust type by pattern matching or using the `into_` functions.
///
/// ## Indexing
///
/// If the value is a php array, you can directly index into the `Value`, this will panic if the `Value` is not an array
///
/// ```rust
/// # use maplit::hashmap;
/// # use php_literal_parser::Value;
/// #
/// # fn main() {
/// let value = Value::Array(hashmap!{
/// "key".into() => "value".into(),
/// 10.into() => false.into()
/// });
/// assert_eq!(value["key"], "value");
/// assert_eq!(value[10], false);
/// # }
/// ```
impl Value { impl Value {
/// Check if the value is a bool /// Check if the value is a bool
pub fn is_bool(&self) -> bool { pub fn is_bool(&self) -> bool {
@ -122,15 +144,45 @@ impl PartialEq<String> for Value {
} }
} }
impl PartialEq<str> for Value { impl PartialEq<&str> for Value {
fn eq(&self, other: &str) -> bool { fn eq(&self, other: &&str) -> bool {
match self { match self {
Value::String(str) => str.as_str() == other, Value::String(str) => str.as_str() == *other,
_ => false, _ => false,
} }
} }
} }
impl From<bool> for Value {
fn from(value: bool) -> Self {
Value::Bool(value)
}
}
impl From<i64> for Value {
fn from(value: i64) -> Self {
Value::Int(value)
}
}
impl From<f64> for Value {
fn from(value: f64) -> Self {
Value::Float(value)
}
}
impl From<String> for Value {
fn from(value: String) -> Self {
Value::String(value)
}
}
impl From<&str> for Value {
fn from(value: &str) -> Self {
Value::String(value.into())
}
}
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]
pub enum Key { pub enum Key {
Int(i64), Int(i64),
@ -158,6 +210,12 @@ impl From<String> for Key {
} }
} }
impl From<&str> for Key {
fn from(str: &str) -> Self {
Key::String(str.into())
}
}
impl Key { impl Key {
/// Check if the key is an integer /// Check if the key is an integer
pub fn is_int(&self) -> bool { pub fn is_int(&self) -> bool {
@ -239,7 +297,7 @@ fn test_index() {
Key::String("key".to_string()) => Value::String("value".to_string()), Key::String("key".to_string()) => Value::String("value".to_string()),
Key::Int(1) => Value::Bool(true), Key::Int(1) => Value::Bool(true),
}); });
assert_eq!(map["key"], Value::String("value".to_string())); assert_eq!(map["key"], "value");
assert_eq!(map[1], Value::Bool(true)); assert_eq!(map[1], true);
assert_eq!(map[Key::Int(1)], Value::Bool(true)); assert_eq!(map[Key::Int(1)], true);
} }