5050//!
5151//! ## Cargo Features
5252//!
53- //! - `serde` (default): Serde serialization/deserialization support
53+ //! By default, sickle includes only the core types (`CclObject`, `Entry`, `Error`).
54+ //! Enable features to add functionality:
55+ //!
56+ //! - `parse`: Core parsing (`parse`, `parse_indented`) - returns flat key-value entries
57+ //! - `hierarchy`: Build hierarchical model (`build_hierarchy`, `load`) - includes `parse`
58+ //! - `printer`: CCL printer for serializing back to canonical CCL text - includes `hierarchy`
59+ //! - `serde-deserialize`: Serde deserialization (`from_str`) - includes `hierarchy`
60+ //! - `serde-serialize`: Serde serialization (`to_string`) - includes `printer`
61+ //! - `serde`: Both serialization and deserialization
5462//! - `intern`: String interning for memory efficiency with large configs
63+ //! - `full`: Enable all features
5564//!
5665//! ### Future Features (Planned)
5766//!
5867//! - `section-headers`: Support `== Section ==` style headers
59- //! - `duplicate-key-lists`: Auto-create lists from duplicate keys
6068//! - `typed-access`: Convenience methods like `get_string()`, `get_int()`
6169//! - `list-indexing`: Advanced list operations and indexing
6270
6371pub mod error;
6472pub mod model;
73+
74+ #[ cfg( feature = "parse" ) ]
6575mod parser;
76+
77+ #[ cfg( feature = "printer" ) ]
6678pub mod printer;
6779
68- #[ cfg( feature = "serde" ) ]
80+ #[ cfg( feature = "serde-deserialize " ) ]
6981pub mod de;
7082
83+ #[ cfg( feature = "serde-serialize" ) ]
84+ pub mod ser;
85+
7186pub use error:: { Error , Result } ;
7287pub use model:: { CclObject , Entry } ;
88+
89+ #[ cfg( feature = "printer" ) ]
7390pub use printer:: { CclPrinter , PrinterConfig } ;
7491
7592/// Parse a CCL string into a flat list of entries
@@ -78,6 +95,8 @@ pub use printer::{CclPrinter, PrinterConfig};
7895/// without building the hierarchical structure. Use `build_hierarchy()` to
7996/// construct the hierarchical model from these entries.
8097///
98+ /// Requires the `parse` feature.
99+ ///
81100/// # Examples
82101///
83102/// ```rust
@@ -93,6 +112,7 @@ pub use printer::{CclPrinter, PrinterConfig};
93112/// assert_eq!(entries[0].key, "name");
94113/// assert_eq!(entries[0].value, "MyApp");
95114/// ```
115+ #[ cfg( feature = "parse" ) ]
96116pub fn parse ( input : & str ) -> Result < Vec < Entry > > {
97117 let map = parser:: parse_to_map ( input) ?;
98118
@@ -112,6 +132,8 @@ pub fn parse(input: &str) -> Result<Vec<Entry>> {
112132/// This is the second step of CCL processing, taking the entries from `parse()`
113133/// and constructing a hierarchical structure with proper nesting and type inference.
114134///
135+ /// Requires the `hierarchy` feature.
136+ ///
115137/// # Examples
116138///
117139/// ```rust
@@ -126,6 +148,7 @@ pub fn parse(input: &str) -> Result<Vec<Entry>> {
126148/// let model = build_hierarchy(&entries).unwrap();
127149/// assert_eq!(model.get_string("name").unwrap(), "MyApp");
128150/// ```
151+ #[ cfg( feature = "hierarchy" ) ]
129152pub fn build_hierarchy ( entries : & [ Entry ] ) -> Result < CclObject > {
130153 // Group entries by key (preserving order with IndexMap)
131154 let mut map: indexmap:: IndexMap < String , Vec < String > > = indexmap:: IndexMap :: new ( ) ;
@@ -141,6 +164,7 @@ pub fn build_hierarchy(entries: &[Entry]) -> Result<CclObject> {
141164
142165/// Check if a string looks like a valid CCL key
143166/// Valid keys: alphanumeric, underscores, dots, hyphens (not leading), slashes for comments
167+ #[ cfg( feature = "hierarchy" ) ]
144168fn is_valid_ccl_key ( key : & str ) -> bool {
145169 if key. is_empty ( ) {
146170 return true ; // Empty keys are valid (for lists)
@@ -168,6 +192,7 @@ fn is_valid_ccl_key(key: &str) -> bool {
168192/// - `key =` (empty value) becomes `{"key": {"": {}}}`
169193/// - Multiple values become multiple nested keys
170194/// - Nested CCL is recursively parsed
195+ #[ cfg( feature = "hierarchy" ) ]
171196fn build_model ( map : indexmap:: IndexMap < String , Vec < String > > ) -> Result < CclObject > {
172197 let mut result = indexmap:: IndexMap :: new ( ) ;
173198
@@ -238,6 +263,8 @@ fn build_model(map: indexmap::IndexMap<String, Vec<String>>) -> Result<CclObject
238263/// This is used for parsing nested CCL values where the entire block may be
239264/// indented in the parent context.
240265///
266+ /// Requires the `parse` feature.
267+ ///
241268/// # Examples
242269///
243270/// ```rust
@@ -247,6 +274,7 @@ fn build_model(map: indexmap::IndexMap<String, Vec<String>>) -> Result<CclObject
247274/// let entries = parse_indented(nested).unwrap();
248275/// assert_eq!(entries.len(), 3);
249276/// ```
277+ #[ cfg( feature = "parse" ) ]
250278pub fn parse_indented ( input : & str ) -> Result < Vec < Entry > > {
251279 // Find the minimum indentation level (common prefix)
252280 let min_indent = input
@@ -293,6 +321,7 @@ pub fn parse_indented(input: &str) -> Result<Vec<Entry>> {
293321}
294322
295323/// Parse all key=value pairs from input as flat entries, ignoring indentation hierarchy
324+ #[ cfg( feature = "parse" ) ]
296325fn parse_flat_entries ( input : & str ) -> Result < Vec < Entry > > {
297326 let mut entries = Vec :: new ( ) ;
298327
@@ -319,6 +348,7 @@ fn parse_flat_entries(input: &str) -> Result<Vec<Entry>> {
319348}
320349
321350/// Parse input as a single entry, preserving the raw value including indentation
351+ #[ cfg( feature = "parse" ) ]
322352fn parse_single_entry_with_raw_value ( input : & str ) -> Result < Vec < Entry > > {
323353 // Find the first line with '='
324354 let mut lines = input. lines ( ) ;
@@ -358,6 +388,8 @@ fn parse_single_entry_with_raw_value(input: &str) -> Result<Vec<Entry>> {
358388/// This is a convenience function that combines `parse()` and `build_hierarchy()`.
359389/// Equivalent to: `build_hierarchy(&parse(input)?)`
360390///
391+ /// Requires the `hierarchy` feature.
392+ ///
361393/// # Examples
362394///
363395/// ```rust
@@ -371,14 +403,18 @@ fn parse_single_entry_with_raw_value(input: &str) -> Result<Vec<Entry>> {
371403/// let model = load(ccl).unwrap();
372404/// assert_eq!(model.get_string("name").unwrap(), "MyApp");
373405/// ```
406+ #[ cfg( feature = "hierarchy" ) ]
374407pub fn load ( input : & str ) -> Result < CclObject > {
375408 let entries = parse ( input) ?;
376409 build_hierarchy ( & entries)
377410}
378411
379- #[ cfg( feature = "serde" ) ]
412+ #[ cfg( feature = "serde-deserialize " ) ]
380413pub use de:: from_str;
381414
415+ #[ cfg( feature = "serde-serialize" ) ]
416+ pub use ser:: to_string;
417+
382418// Unit tests removed - all functionality is covered by data-driven tests in:
383419// - api_core_ccl_parsing.json (basic parsing, multiline values, equals in values)
384420// - api_core_ccl_hierarchy.json (build_hierarchy, nested structures, duplicate keys to lists)
0 commit comments