Skip to main content

oxgraph_db/
value.rs

1//! Typed property and query values.
2
3use std::fmt;
4
5use serde::{Deserialize, Serialize};
6
7/// Supported scalar property types.
8///
9/// # Performance
10///
11/// Copying and comparing a type tag are `O(1)`.
12#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
13pub enum PropertyType {
14    /// Boolean property.
15    Boolean,
16    /// Signed 64-bit integer property.
17    Integer,
18    /// UTF-8 text property.
19    Text,
20}
21
22/// One typed property value.
23///
24/// # Performance
25///
26/// Copying is `O(value length)` for text and `O(1)` otherwise.
27#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
28pub enum PropertyValue {
29    /// Boolean value.
30    Boolean(bool),
31    /// Signed integer value.
32    Integer(i64),
33    /// UTF-8 text value.
34    Text(String),
35}
36
37impl PropertyValue {
38    /// Returns this value's type tag.
39    ///
40    /// # Performance
41    ///
42    /// This function is `O(1)`.
43    #[must_use]
44    pub const fn value_type(&self) -> PropertyType {
45        match self {
46            Self::Boolean(_value) => PropertyType::Boolean,
47            Self::Integer(_value) => PropertyType::Integer,
48            Self::Text(_value) => PropertyType::Text,
49        }
50    }
51}
52
53impl fmt::Display for PropertyValue {
54    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
55        match self {
56            Self::Boolean(value) => write!(formatter, "{value}"),
57            Self::Integer(value) => write!(formatter, "{value}"),
58            Self::Text(value) => formatter.write_str(value),
59        }
60    }
61}
62
63/// Property value parser used by CLI, HTTP, `OxQL`, and Cypher tests.
64///
65/// # Errors
66///
67/// Returns the original token when it cannot be parsed as a supported value.
68///
69/// # Performance
70///
71/// This function is `O(token.len())`.
72pub(crate) fn parse_value_token(token: &str) -> Result<PropertyValue, String> {
73    let trimmed = token.trim();
74    if trimmed == "true" {
75        return Ok(PropertyValue::Boolean(true));
76    }
77    if trimmed == "false" {
78        return Ok(PropertyValue::Boolean(false));
79    }
80    if let Ok(value) = trimmed.parse::<i64>() {
81        return Ok(PropertyValue::Integer(value));
82    }
83    parse_quoted(trimmed).map(PropertyValue::Text)
84}
85
86/// Parses one single- or double-quoted token.
87fn parse_quoted(token: &str) -> Result<String, String> {
88    let single = token
89        .strip_prefix('\'')
90        .and_then(|text| text.strip_suffix('\''));
91    let double = token
92        .strip_prefix('"')
93        .and_then(|text| text.strip_suffix('"'));
94    single
95        .or(double)
96        .map_or_else(|| Err(token.to_owned()), |value| Ok(value.to_owned()))
97}