Skip to content

Commit

Permalink
types: Add .set_coerce() to MarkedScalarNode
Browse files Browse the repository at this point in the history
To enable nodes to be locked down so that they do not coerce
to booleans, integers, etc. we have a .set_coerce() which is
honoured by the various .as_*() functions.

Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
  • Loading branch information
kinnison committed Jun 6, 2024
1 parent 8fec8a0 commit c47d0d0
Showing 1 changed file with 47 additions and 7 deletions.
54 changes: 47 additions & 7 deletions marked-yaml/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ pub enum Node {
pub struct MarkedScalarNode {
span: Span,
value: String,
may_coerce: bool,
}

pub(crate) type MappingHash = LinkedHashMap<MarkedScalarNode, Node>;
Expand Down Expand Up @@ -690,6 +691,7 @@ impl MarkedScalarNode {
Self {
span,
value: String::new(),
may_coerce: true,
}
}

Expand All @@ -703,6 +705,7 @@ impl MarkedScalarNode {
Self {
span,
value: content.into().into_owned(),
may_coerce: true,
}
}

Expand All @@ -719,6 +722,23 @@ impl MarkedScalarNode {
self.value.as_str()
}

/// Enable or disable permission to coerce values
///
/// The various [`as_bool()`][Self::as_bool()] and other methods
/// which can coerce a string can be forced to always deny
/// coercion.
///
/// ```
/// # use marked_yaml::types::*;
/// let mut node: MarkedScalarNode = "true".into();
/// assert_eq!(node.as_bool(), Some(true));
/// node.set_coerce(false);
/// assert_eq!(node.as_bool(), None);
/// ```
pub fn set_coerce(&mut self, may_coerce: bool) {
self.may_coerce = may_coerce;
}

/// Treat the scalar node as a boolean
///
/// If the scalar contains any of the following then it is true:
Expand All @@ -735,6 +755,9 @@ impl MarkedScalarNode {
///
/// Everything else is not a boolean and so will return None
///
/// Note: If you have done [`.set_coerce(false)`](MarkedScalarNode::set_coerce())
/// then no matter the string's value, this will return `None`.
///
/// ```
/// # use marked_yaml::types::*;
/// let node: MarkedScalarNode = "true".into();
Expand All @@ -743,12 +766,19 @@ impl MarkedScalarNode {
/// assert_eq!(node.as_bool(), Some(false));
/// let node: MarkedScalarNode = "NO".into(); // YAML boolean, but not for us
/// assert_eq!(node.as_bool(), None);
/// let mut node: MarkedScalarNode = "true".into();
/// node.set_coerce(false);
/// assert_eq!(node.as_bool(), None);
/// ```
pub fn as_bool(&self) -> Option<bool> {
match self.value.as_str() {
"true" | "True" | "TRUE" => Some(true),
"false" | "False" | "FALSE" => Some(false),
_ => None,
if self.may_coerce {
match self.value.as_str() {
"true" | "True" | "TRUE" => Some(true),
"false" | "False" | "FALSE" => Some(false),
_ => None,
}
} else {
None
}
}
}
Expand Down Expand Up @@ -830,19 +860,29 @@ a number of the right kind then return it. This is essentially
a shortcut for using the `FromStr` trait on the return value of
`.as_str()`.
Note, this honours the setting of [`MarkedScalarNode::set_coerce()`]
```
# use marked_yaml::types::*;
let node: MarkedScalarNode = "0".into();
let mut node: MarkedScalarNode = "0".into();
assert_eq!(node.as_"#,
stringify!($t),
r#"(), Some(0"#,
stringify!($t),
r#"));
node.set_coerce(false);
assert_eq!(node.as_"#,
stringify!($t),
r#"(), None);
```"#
),
pub fn $as(&self) -> Option<$t> {
use std::str::FromStr;
$t::from_str(&self.value).ok()
if self.may_coerce {
use std::str::FromStr;
$t::from_str(&self.value).ok()
} else {
None
}
}
);
}
Expand Down

0 comments on commit c47d0d0

Please sign in to comment.