use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct GoldFile {
pub blocks: Vec<Block>,
}
impl GoldFile {
pub fn new() -> Self {
Self { blocks: Vec::new() }
}
pub fn add_block(&mut self, block: Block) {
self.blocks.push(block);
}
pub fn blocks_of_type(&self, block_type: &str) -> Vec<&Block> {
self.blocks
.iter()
.filter(|b| b.block_type() == block_type)
.collect()
}
}
impl Default for GoldFile {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub enum Block {
Config(ConfigBlock),
Schema(SchemaBlock),
Query(QueryBlock),
Endpoint(EndpointBlock),
Data(DataBlock),
Custom(CustomBlock),
}
impl Block {
pub fn block_type(&self) -> &str {
match self {
Block::Config(_) => "config",
Block::Schema(_) => "schema",
Block::Query(_) => "query",
Block::Endpoint(_) => "endpoint",
Block::Data(_) => "data",
Block::Custom(c) => &c.block_type,
}
}
pub fn name(&self) -> Option<&str> {
match self {
Block::Config(c) => Some(&c.name),
Block::Schema(s) => Some(&s.name),
Block::Query(q) => Some(&q.name),
Block::Endpoint(e) => Some(&e.path),
Block::Data(d) => Some(&d.name),
Block::Custom(c) => c.name.as_deref(),
}
}
}
#[derive(Debug, Clone)]
pub struct ConfigBlock {
pub name: String,
pub attributes: HashMap<String, Value>,
}
#[derive(Debug, Clone)]
pub struct SchemaBlock {
pub name: String,
pub format: Option<String>,
pub fields: Vec<SchemaField>,
pub content: Option<String>, pub crud: bool, }
#[derive(Debug, Clone)]
pub struct SchemaField {
pub name: String,
pub field_type: String,
pub nullable: bool,
pub default: Option<Value>,
pub embedding_annotation: Option<EmbeddingAnnotation>,
}
#[derive(Debug, Clone)]
pub struct EmbeddingAnnotation {
pub model: String,
pub source_field: String,
pub dimension: Option<usize>,
pub paradigm: Option<String>,
}
#[derive(Debug, Clone)]
pub struct QueryBlock {
pub name: String,
pub params: Vec<Parameter>,
pub return_type: String,
pub language: String,
pub source: String,
}
#[derive(Debug, Clone)]
pub struct Parameter {
pub name: String,
pub param_type: String,
}
#[derive(Debug, Clone)]
pub struct EndpointBlock {
pub method: String,
pub path: String,
pub query: String,
pub auth: bool,
pub params: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub struct DataBlock {
pub name: String,
pub format: String,
pub content: String,
}
#[derive(Debug, Clone)]
pub struct CustomBlock {
pub block_type: String,
pub name: Option<String>,
pub attributes: HashMap<String, Value>,
pub content: Option<String>,
}
#[derive(Debug, Clone)]
pub enum Value {
String(String),
Integer(i64),
Float(f64),
Boolean(bool),
List(Vec<Value>),
Map(HashMap<String, Value>),
}
impl Value {
pub fn as_string(&self) -> Option<&str> {
match self {
Value::String(s) => Some(s),
_ => None,
}
}
pub fn as_int(&self) -> Option<i64> {
match self {
Value::Integer(i) => Some(*i),
_ => None,
}
}
pub fn as_bool(&self) -> Option<bool> {
match self {
Value::Boolean(b) => Some(*b),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gold_file_creation() {
let file = GoldFile::new();
assert_eq!(file.blocks.len(), 0);
}
#[test]
fn test_block_type() {
let config = Block::Config(ConfigBlock {
name: "database".to_string(),
attributes: HashMap::new(),
});
assert_eq!(config.block_type(), "config");
}
#[test]
fn test_value_types() {
let str_val = Value::String("test".to_string());
assert_eq!(str_val.as_string(), Some("test"));
let int_val = Value::Integer(42);
assert_eq!(int_val.as_int(), Some(42));
let bool_val = Value::Boolean(true);
assert_eq!(bool_val.as_bool(), Some(true));
}
}