API Reference
Rust API reference for the zoko-parser crate
The zoko-parser crate provides a Rust API for parsing and manipulating Zoko files.
Installation
Add to your Cargo.toml:
[dependencies]
zoko-parser = "0.1"Core Functions
parse_zoko
Parse a Zoko string into a ZokoFile structure.
use zoko_parser::parse_zoko;
fn main() {
let zoko_content = r#"
name: "My Application",
version: "1.0.0",
debug: true,
"#;
match parse_zoko(zoko_content) {
Ok(zoko_file) => {
println!("Parsed {} entries", zoko_file.entries.len());
}
Err(e) => {
eprintln!("Parse error: {}", e);
}
}
}Signature:
pub fn parse_zoko(input: &str) -> Result<ZokoFile, ParseErrorKind>Parameters:
input: A string slice containing Zoko content
Returns:
Ok(ZokoFile): Successfully parsed Zoko fileErr(ParseErrorKind): Parse error with details
parse_zoko_to_json
Parse a Zoko string and convert it to a JSON string.
use zoko_parser::parse_zoko_to_json;
fn main() {
let zoko_content = r#"
name: "My Application",
version: "1.0.0",
"#;
match parse_zoko_to_json(zoko_content) {
Ok(json) => {
println!("{}", json);
}
Err(e) => {
eprintln!("Conversion error: {}", e);
}
}
}Signature:
pub fn parse_zoko_to_json(input: &str) -> Result<String, ParseErrorKind>Parameters:
input: A string slice containing Zoko content
Returns:
Ok(String): JSON string representationErr(ParseErrorKind): Parse error with details
Data Structures
ZokoFile
The main structure representing a parsed Zoko file.
pub struct ZokoFile {
pub entries: IndexMap<String, Value>,
}Fields:
entries: Ordered map of key-value pairs (uses IndexMap for order preservation)
Value
Enum representing all possible values in a Zoko file.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
String(String),
Number(f64),
Boolean(bool),
Array(Vec<Value>),
Object(IndexMap<String, Value>),
Null,
}Variants:
String(String): Text dataNumber(f64): Numeric valuesBoolean(bool): True/false valuesArray(Vec<Value>): Ordered list of valuesObject(IndexMap<String, Value>): Key-value mappingsNull: Absence of value
ParseErrorKind
Error type for parsing errors.
#[derive(Debug, Error)]
pub enum ParseErrorKind {
#[error("Unexpected character: {0}")]
UnexpectedChar(char),
#[error("Unexpected end of input")]
UnexpectedEof,
#[error("Invalid number format: {0}")]
InvalidNumber(String),
#[error("Invalid escape sequence: {0}")]
InvalidEscape(String),
#[error("Expected {expected}, found {found}")]
Expected { expected: String, found: String },
}Usage Examples
Reading and Parsing a File
use std::fs;
use zoko_parser::parse_zoko;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let content = fs::read_to_string("config.zo")?;
let zoko_file = parse_zoko(&content)?;
println!("Parsed {} entries", zoko_file.entries.len());
Ok(())
}Accessing Parsed Values
use zoko_parser::parse_zoko;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let content = r#"
name: "My App",
version: "1.0.0",
debug: true,
"#;
let zoko_file = parse_zoko(content)?;
// Access values
if let Some(Value::String(name)) = zoko_file.entries.get("name") {
println!("Application name: {}", name);
}
if let Some(Value::Boolean(debug)) = zoko_file.entries.get("debug") {
println!("Debug mode: {}", debug);
}
Ok(())
}Working with Nested Structures
use zoko_parser::parse_zoko;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let content = r#"
config: {
database: {
host: "localhost",
port: 5432,
},
},
"#;
let zoko_file = parse_zoko(content)?;
// Access nested values
if let Some(Value::Object(config)) = zoko_file.entries.get("config") {
if let Some(Value::Object(database)) = config.get("database") {
if let Some(Value::String(host)) = database.get("host") {
println!("Database host: {}", host);
}
}
}
Ok(())
}Working with Arrays
use zoko_parser::parse_zoko;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let content = r#"
tags: ["production", "api"],
servers: [
{host: "server1", port: 8080},
{host: "server2", port: 8080},
],
"#;
let zoko_file = parse_zoko(content)?;
// Access array values
if let Some(Value::Array(tags)) = zoko_file.entries.get("tags") {
for tag in tags {
if let Value::String(tag_str) = tag {
println!("Tag: {}", tag_str);
}
}
}
// Access array of objects
if let Some(Value::Array(servers)) = zoko_file.entries.get("servers") {
for server in servers {
if let Value::Object(server_obj) = server {
if let Some(Value::String(host)) = server_obj.get("host") {
println!("Server: {}", host);
}
}
}
}
Ok(())
}Converting to Custom Types
use serde::Deserialize;
use zoko_parser::{parse_zoko, Value};
#[derive(Debug, Deserialize)]
struct Config {
name: String,
version: String,
debug: bool,
}
impl TryFrom<zoko_parser::ZokoFile> for Config {
type Error = String;
fn try_from(zoko_file: zoko_parser::ZokoFile) -> Result<Self, Self::Error> {
// Convert ZokoFile to your custom type
let json = serde_json::to_string(&zoko_file)
.map_err(|e| e.to_string())?;
serde_json::from_str(&json)
.map_err(|e| e.to_string())
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let content = r#"
name: "My App",
version: "1.0.0",
debug: true,
"#;
let zoko_file = parse_zoko(content)?;
let config: Config = zoko_file.try_into()?;
println!("Config: {:?}", config);
Ok(())
}Error Handling
use zoko_parser::{parse_zoko, ParseErrorKind};
fn main() {
let content = r#"
name: "My App",
version: 1.0.0, // Invalid: should be "1.0.0"
"#;
match parse_zoko(content) {
Ok(zoko_file) => {
println!("Successfully parsed");
}
Err(ParseErrorKind::InvalidNumber(num)) => {
eprintln!("Invalid number format: {}", num);
}
Err(ParseErrorKind::Expected { expected, found }) => {
eprintln!("Expected {}, found {}", expected, found);
}
Err(e) => {
eprintln!("Parse error: {}", e);
}
}
}Serialization
The ZokoFile and Value types implement Serialize and Deserialize from serde, making them compatible with JSON and other formats.
Serialize to JSON
use zoko_parser::parse_zoko;
use serde_json;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let content = r#"
name: "My App",
version: "1.0.0",
"#;
let zoko_file = parse_zoko(content)?;
let json = serde_json::to_string_pretty(&zoko_file)?;
println!("{}", json);
Ok(())
}Deserialize from JSON
use zoko_parser::ZokoFile;
use serde_json;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let json = r#"{
"entries": {
"name": "My App",
"version": "1.0.0"
}
}"#;
let zoko_file: ZokoFile = serde_json::from_str(json)?;
println!("Parsed {} entries", zoko_file.entries.len());
Ok(())
}Performance Considerations
- Order Preservation: The use of
IndexMapensures order preservation but has slightly higher memory overhead thanHashMap - Parsing Speed: The parser uses nom combinators for efficient parsing
- Memory Usage: Large files are parsed entirely into memory; consider streaming for very large files
Thread Safety
The ZokoFile and Value types are Send and Sync when their contents are Send and Sync, making them safe to share across threads.
Integration with Other Crates
Use with Serde
use zoko_parser::{parse_zoko, Value};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct AppConfig {
#[serde(flatten)]
entries: IndexMap<String, Value>,
}Use with Clap
use clap::Parser;
use zoko_parser::parse_zoko;
#[derive(Parser)]
struct Cli {
#[arg(short, long)]
config: String,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
let content = std::fs::read_to_string(cli.config)?;
let zoko_file = parse_zoko(&content)?;
println!("Parsed configuration");
Ok(())
}2026 © All Rights Reserved.
- All the content is available under CC BY-SA 4.0, expect where otherwise stated.
- Source code is available on GitLab, licensed under Apache 2.0.
Last updated on
