pub struct CclObject(/* private fields */);Expand description
Represents a parsed CCL document as a recursive map structure
Following the OCaml implementation: type entry_map = value_entry list KeyMap.t
A CCL document is a fixed-point recursive structure where:
- Every Model is a map from String to
Vec<Model> - An empty map {} represents a leaf/terminal value
- String values are encoded in the recursive structure
- Lists are represented as multiple entries with the same key
- Uses IndexMap to preserve insertion order (keys ordered by first appearance)
- Uses Vec to preserve order of values for each key (insertion order)
Implementations§
Source§impl CclObject
impl CclObject
Sourcepub fn get(&self, key: &str) -> Result<&CclObject>
pub fn get(&self, key: &str) -> Result<&CclObject>
Get a value by key, returning an error if the key doesn’t exist
If the key has multiple values, returns the first one (matching OCaml behavior).
Use get_all() to get all values for a key.
Sourcepub fn get_all(&self, key: &str) -> Result<&[CclObject]>
pub fn get_all(&self, key: &str) -> Result<&[CclObject]>
Get all values for a key, returning an error if the key doesn’t exist
Sourcepub fn keys(&self) -> impl Iterator<Item = &String>
pub fn keys(&self) -> impl Iterator<Item = &String>
Get an iterator over the keys in this model
Sourcepub fn values(&self) -> impl Iterator<Item = &CclObject>
pub fn values(&self) -> impl Iterator<Item = &CclObject>
Get an iterator over the first value for each key
This flattens the Vec structure, returning only the first value per key.
Use iter_all() to get all values.
Sourcepub fn iter(&self) -> impl Iterator<Item = (&String, &CclObject)>
pub fn iter(&self) -> impl Iterator<Item = (&String, &CclObject)>
Get an iterator over key-value pairs (first value only per key)
This flattens the Vec structure, returning only the first value per key.
Use iter_all() to get all key-value pairs including duplicates.
Sourcepub fn iter_all(&self) -> impl Iterator<Item = (&String, &CclObject)>
pub fn iter_all(&self) -> impl Iterator<Item = (&String, &CclObject)>
Get an iterator over all key-value pairs including duplicate keys
Sourcepub fn inner_mut(&mut self) -> &mut IndexMap<String, Vec<CclObject>>
pub fn inner_mut(&mut self) -> &mut IndexMap<String, Vec<CclObject>>
Get mutable access to the internal IndexMap for direct manipulation
This allows programmatic construction of CCL structures when you need full control over the data model.
§Example
use sickle::CclObject;
let mut obj = CclObject::new();
let map = obj.inner_mut();
map.insert("key".to_string(), vec![CclObject::from_string("value")]);Sourcepub fn empty() -> Self
pub fn empty() -> Self
Create an empty CclObject (represents an empty value in CCL: key =)
§Example
use sickle::CclObject;
let empty = CclObject::empty();
// Represents: key =Sourcepub fn from_list(items: Vec<impl Into<String>>) -> Self
pub fn from_list(items: Vec<impl Into<String>>) -> Self
Create a CclObject representing a list using bare list syntax
In CCL, a list is represented using the same empty key with multiple values.
Now that we use Vec<CclObject> internally, we can properly support duplicate keys.
§Example
use sickle::CclObject;
let list = CclObject::from_list(vec!["brew", "scoop", "pacman"]);
// Represents:
// packages =
// = brew
// = scoop
// = pacmanSourcepub fn add_comment(&mut self, text: impl Into<String>)
pub fn add_comment(&mut self, text: impl Into<String>)
Add a comment entry to this CclObject
CCL comments use the /= prefix followed by the comment text as the key,
with an empty value. This method adds a comment entry directly to the object.
§Example
use sickle::CclObject;
let mut obj = CclObject::new();
obj.add_comment("Generated file - do not edit");
// When printed, represents: /= Generated file - do not editSourcepub fn add_blank_line(&mut self)
pub fn add_blank_line(&mut self)
Add a blank line entry to this CclObject
Blank lines in CCL output are represented as entries with an empty key and empty value. This is useful for visual separation in generated files.
§Example
use sickle::CclObject;
let mut obj = CclObject::new();
obj.add_comment("Header section");
obj.add_blank_line();
// When printed, adds visual separationSourcepub fn compose(&self, other: &CclObject) -> CclObject
pub fn compose(&self, other: &CclObject) -> CclObject
Compose two CCL objects together (monoid binary operation)
This implements the fundamental CCL composition operation that makes CCL a monoid. When composing two objects:
- Keys unique to either object are preserved
- Keys present in both are recursively composed
- The empty object is the identity element
§Algebraic Properties
- Associativity:
a.compose(&b).compose(&c) == a.compose(&b.compose(&c)) - Left Identity:
CclObject::new().compose(&x) == x - Right Identity:
x.compose(&CclObject::new()) == x
§Example
use sickle::{load, CclObject};
let a = load("config =\n host = localhost").unwrap();
let b = load("config =\n port = 8080").unwrap();
let composed = a.compose(&b);
// Result: config = { host = localhost, port = 8080 }Sourcepub fn compose_associative(a: &CclObject, b: &CclObject, c: &CclObject) -> bool
pub fn compose_associative(a: &CclObject, b: &CclObject, c: &CclObject) -> bool
Check if composing three objects is associative
Tests: (a ∘ b) ∘ c == a ∘ (b ∘ c)
This is used for testing the algebraic properties of CCL.
Sourcepub fn identity_left(x: &CclObject) -> bool
pub fn identity_left(x: &CclObject) -> bool
Check left identity property
Tests: empty ∘ x == x
Sourcepub fn identity_right(x: &CclObject) -> bool
pub fn identity_right(x: &CclObject) -> bool
Check right identity property
Tests: x ∘ empty == x
Sourcepub fn get_string(&self, key: &str) -> Result<&str>
pub fn get_string(&self, key: &str) -> Result<&str>
Get a string value by key
Looks up the key and extracts its string representation
Sourcepub fn get_bool(&self, key: &str) -> Result<bool>
pub fn get_bool(&self, key: &str) -> Result<bool>
Get a boolean value by key (strict mode)
Only accepts “true” and “false”. For lenient parsing that also
accepts “yes” and “no”, use get_bool_lenient().
Sourcepub fn get_bool_with_options(
&self,
key: &str,
options: BoolOptions,
) -> Result<bool>
pub fn get_bool_with_options( &self, key: &str, options: BoolOptions, ) -> Result<bool>
Get a boolean value by key with options
Allows configuring boolean parsing behavior.
Sourcepub fn get_bool_lenient(&self, key: &str) -> Result<bool>
pub fn get_bool_lenient(&self, key: &str) -> Result<bool>
Get a boolean value by key (lenient mode)
Accepts “true”, “false”, “yes”, and “no”.
For strict parsing, use get_bool().
Sourcepub fn get_list(&self, key: &str) -> Result<Vec<String>>
pub fn get_list(&self, key: &str) -> Result<Vec<String>>
Get a list of string values by key (reference-compliant behavior)
Only bare list syntax produces lists. Duplicate keys with values are NOT treated as lists.
For typed access to lists of scalars, use get_list_typed::<T>() instead.
For coercion behavior, use get_list_coerced().
Sourcepub fn get_list_coerced(&self, key: &str) -> Result<Vec<String>>
pub fn get_list_coerced(&self, key: &str) -> Result<Vec<String>>
Get a list of string values by key (with coercion)
Duplicate keys are coerced into lists, and scalar literals are filtered.
When multiple entries exist for the same key (e.g., servers = web1\nservers = web2),
all values are collected into a single list.
For typed access to lists of scalars, use get_list_typed::<T>() instead.
For reference-compliant behavior, use get_list().
Sourcepub fn get_list_typed<T>(&self, key: &str) -> Result<Vec<T>>
pub fn get_list_typed<T>(&self, key: &str) -> Result<Vec<T>>
Get a typed list of values by key
This method provides generic access to lists of any parseable type.
Unlike get_list(), this doesn’t filter scalar literals - it parses all keys as type T.
§Examples
// Numbers list
let input = "numbers = 1\nnumbers = 42\nnumbers = -17";
let entries = parse(input)?;
let model = build_hierarchy(&entries)?;
let numbers: Vec<i64> = model.get_list_typed("numbers")?;
assert_eq!(numbers, vec![1, 42, -17]);
// Booleans list
let input = "flags = true\nflags = false";
let entries = parse(input)?;
let model = build_hierarchy(&entries)?;
let flags: Vec<bool> = model.get_list_typed("flags")?;
assert_eq!(flags, vec![true, false]);§Errors
Returns Error::ValueError if any key cannot be parsed as type T.
Sourcepub fn from_string(s: impl Into<String>) -> Self
pub fn from_string(s: impl Into<String>) -> Self
Create a CclObject representing a string value
In CCL, a string is represented as a map with a single key (the string)
and an empty value: {"string_value": [{}]}
§Example
use sickle::CclObject;
let val = CclObject::from_string("hello");
// Represents: key = helloTrait Implementations§
impl Eq for CclObject
impl StructuralPartialEq for CclObject
Auto Trait Implementations§
impl Freeze for CclObject
impl RefUnwindSafe for CclObject
impl Send for CclObject
impl Sync for CclObject
impl Unpin for CclObject
impl UnsafeUnpin for CclObject
impl UnwindSafe for CclObject
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.