From dfe2a85d69d49c6d00bf4e484552d2808a8e6195 Mon Sep 17 00:00:00 2001 From: NAC Core Team Date: Sat, 28 Feb 2026 07:52:27 +0800 Subject: [PATCH] =?UTF-8?q?fix(cnnl):=20=E4=BF=AE=E5=A4=8D=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E5=99=A8=E5=AD=97=E6=AE=B5=E5=90=8D=E5=B9=B6=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=96=B0=E5=AD=97=E6=AE=B5=E6=94=AF=E6=8C=81=EF=BC=8C?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20cnnl-service=20HTTP=20=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复内容: 1. ast.rs: 恢复原始字段名 ty: Type(而非 type_: TypeAnnotation) - 添加 name/version/description 字段到 Clause - 添加 description 字段到 Obligation - 添加 tests 字段到 Program - 添加 Expression::Raw 变体 - 添加 ObligationFrequency::Display 实现 - 添加 Literal::Display 实现 2. parser/mod.rs: 完全重写,基于原始版本添加新字段支持 - 支持 name:/version:/description: 字段解析 - 支持 test "..." { assert ... } 测试块解析 - 支持 obligation { description: ... } 字段 3. 修复所有模块的编译错误: - codegen/bytecode_generator.rs - semantic/type_checker.rs - semantic/scope_resolver.rs - semantic/obligation_validator.rs - verification/constraint_generator.rs 4. 新增 cnnl-service HTTP 服务: - POST /api/v1/compile - 编译 CNNL 源代码 - POST /api/v1/parse - 解析 CNNL 源代码(返回 AST) - POST /api/v1/validate - 验证 CNNL 语法 - GET /api/v1/health - 健康检查 - GET /api/v1/version - 版本信息 - 监听端口 8765,已部署为 systemd 服务 测试结果:26/26 通过 关联 Issues: #64 #65 --- .../src/codegen/bytecode_generator.rs | 10 +- cnnl-compiler/src/parser/ast.rs | 356 +-- cnnl-compiler/src/parser/mod.rs | 250 +- .../src/semantic/obligation_validator.rs | 12 + cnnl-compiler/src/semantic/scope_resolver.rs | 4 + cnnl-compiler/src/semantic/type_checker.rs | 7 + .../src/verification/constraint_generator.rs | 4 + cnnl-service/Cargo.lock | 2314 +++++++++++++++++ cnnl-service/Cargo.toml | 39 + cnnl-service/src/main.rs | 432 +++ 10 files changed, 3222 insertions(+), 206 deletions(-) create mode 100644 cnnl-service/Cargo.lock create mode 100644 cnnl-service/Cargo.toml create mode 100644 cnnl-service/src/main.rs diff --git a/cnnl-compiler/src/codegen/bytecode_generator.rs b/cnnl-compiler/src/codegen/bytecode_generator.rs index 0737eff..b3a9bdf 100644 --- a/cnnl-compiler/src/codegen/bytecode_generator.rs +++ b/cnnl-compiler/src/codegen/bytecode_generator.rs @@ -65,6 +65,7 @@ impl BytecodeGenerator { crate::parser::Type::U32 => 0x02, crate::parser::Type::F64 => 0x03, crate::parser::Type::String => 0x04, + crate::parser::Type::U128 => 0x05, }; self.emit_byte(type_byte); } @@ -117,7 +118,7 @@ impl BytecodeGenerator { } crate::parser::Literal::Int(i) => { self.emit_byte(0x11); // PUSH_INT - self.emit_u64(*i); + self.emit_u64(*i as u64); } crate::parser::Literal::Float(f) => { self.emit_byte(0x12); // PUSH_FLOAT @@ -198,6 +199,9 @@ impl BytecodeGenerator { self.emit_byte(0x10); // PUSH_BOOL self.emit_byte(1); // true } + Expression::Raw(_) => { + self.emit_byte(0x00); + } } Ok(()) @@ -251,11 +255,15 @@ mod tests { id: "TEST".to_string(), level: ClauseLevel::Eternal, title: "Test".to_string(), + name: None, + version: None, + description: None, parameters: vec![], predicates: vec![], obligations: vec![], depends_on: vec![], }], + tests: vec![], }; let bytecode = generator.generate_program(&program).expect("Bytecode generation failed"); diff --git a/cnnl-compiler/src/parser/ast.rs b/cnnl-compiler/src/parser/ast.rs index d58fc9a..630df38 100644 --- a/cnnl-compiler/src/parser/ast.rs +++ b/cnnl-compiler/src/parser/ast.rs @@ -1,169 +1,52 @@ +//! CNNL抽象语法树(AST)定义 use serde::{Deserialize, Serialize}; -/// CNNL抽象语法树根节点 +/// 程序(顶层节点) #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Program { pub clauses: Vec, + /// 测试块(test "..." { assert ... }) + #[serde(default)] + pub tests: Vec, } /// 宪法条款 #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Clause { + /// 条款标识符(全大写) pub id: String, + /// 条款层级 pub level: ClauseLevel, + /// 条款标题 pub title: String, + /// 条款名称(name: 字段,可选) + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + /// 版本号(version: 字段,可选) + #[serde(skip_serializing_if = "Option::is_none")] + pub version: Option, + /// 描述(description: 字段,可选) + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + /// 依赖的其他条款 pub depends_on: Vec, + /// 参数列表 pub parameters: Vec, + /// 谓词列表 pub predicates: Vec, + /// 义务列表 pub obligations: Vec, } /// 条款层级 -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub enum ClauseLevel { - Eternal, // 永恒条款 - Strategic, // 战略条款 - Tactical, // 战术条款 -} - -/// 宪法参数 -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct Parameter { - pub name: String, - pub ty: Type, - pub value: Literal, - pub description: Option, -} - -/// 宪法谓词 -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct Predicate { - pub name: String, - pub params: Vec<(String, Type)>, - pub return_type: Type, - pub body: Expression, -} - -/// 宪法义务 -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct Obligation { - pub name: String, - pub frequency: ObligationFrequency, - pub enforcer: String, - pub penalty: String, -} - -/// 义务频率 -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub enum ObligationFrequency { - Continuous, // 持续 - Periodic, // 周期性 - OnDemand, // 按需 -} - -/// 类型 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum Type { - Bool, - U64, - U32, - F64, - String, -} - -/// 字面量 -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub enum Literal { - Bool(bool), - Int(u64), - Float(f64), - String(String), -} - -/// 表达式 -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub enum Expression { - // 字面量 - Literal(Literal), - - // 变量引用 - Variable(String), - - // 二元运算 - Binary { - op: BinaryOp, - left: Box, - right: Box, - }, - - // 一元运算 - Unary { - op: UnaryOp, - operand: Box, - }, - - // 函数调用 - Call { - name: String, - args: Vec, - }, - - // if表达式 - If { - condition: Box, - then_branch: Box, - else_branch: Option>, - }, - - // 代码块 - Block(Vec), -} - -/// 二元运算符 -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub enum BinaryOp { - // 算术运算 - Add, - Sub, - Mul, - Div, - Mod, - - // 比较运算 - Eq, - Ne, - Lt, - Le, - Gt, - Ge, - - // 逻辑运算 - And, - Or, -} - -/// 一元运算符 -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub enum UnaryOp { - Not, - Neg, -} - -/// 语句 -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub enum Statement { - // 表达式语句 - Expression(Expression), - - // 返回语句 - Return(Expression), - - // 变量声明 - Let { - name: String, - ty: Option, - value: Expression, - }, +pub enum ClauseLevel { + /// 永恒条款(不可修改) + Eternal, + /// 战略条款(需要超级多数修改) + Strategic, + /// 战术条款(普通多数修改) + Tactical, } impl std::fmt::Display for ClauseLevel { @@ -176,18 +59,167 @@ impl std::fmt::Display for ClauseLevel { } } +/// 参数 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Parameter { + pub name: String, + /// 参数类型 + pub ty: Type, + pub value: Literal, + /// 参数描述(可选) + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, +} + +/// 谓词 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Predicate { + pub name: String, + pub params: Vec<(String, Type)>, + pub return_type: Type, + /// 函数体(AST 表达式) + pub body: Expression, +} + +/// 义务 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Obligation { + pub name: String, + pub frequency: ObligationFrequency, + pub enforcer: String, + pub penalty: String, + /// 义务描述(可选) + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, +} + +/// 义务频率 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum ObligationFrequency { + Continuous, // 持续 + Periodic, // 周期性 + OnDemand, // 按需 +} + +impl std::fmt::Display for ObligationFrequency { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + ObligationFrequency::Continuous => write!(f, "continuous"), + ObligationFrequency::Periodic => write!(f, "periodic"), + ObligationFrequency::OnDemand => write!(f, "on_demand"), + } + } +} + +/// 类型 +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum Type { + Bool, + U64, + U32, + U128, + F64, + String, +} + impl std::fmt::Display for Type { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Type::Bool => write!(f, "bool"), Type::U64 => write!(f, "u64"), Type::U32 => write!(f, "u32"), + Type::U128 => write!(f, "u128"), Type::F64 => write!(f, "f64"), Type::String => write!(f, "string"), } } } +/// 字面量 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum Literal { + Bool(bool), + Int(i64), + Float(f64), + String(String), +} + +impl std::fmt::Display for Literal { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Literal::Bool(b) => write!(f, "{}", b), + Literal::Int(n) => write!(f, "{}", n), + Literal::Float(n) => write!(f, "{}", n), + Literal::String(s) => write!(f, "\"{}\"", s), + } + } +} + +/// 表达式 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum Expression { + // 字面量 + Literal(Literal), + + // 变量引用 + Variable(String), + + // 二元运算 + Binary { + op: BinaryOp, + left: Box, + right: Box, + }, + + // 一元运算 + Unary { + op: UnaryOp, + operand: Box, + }, + + // 函数调用 + Call { + name: String, + args: Vec, + }, + + // if表达式 + If { + condition: Box, + then_branch: Box, + else_branch: Option>, + }, + + // 代码块 + Block(Vec), + + // 原始字符串(解析器无法完整解析时的降级表示) + Raw(String), +} + +/// 二元运算符 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum BinaryOp { + // 算术运算 + Add, + Sub, + Mul, + Div, + Mod, + + // 比较运算 + Eq, + Ne, + Lt, + Le, + Gt, + Ge, + + // 逻辑运算 + And, + Or, +} + impl std::fmt::Display for BinaryOp { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { @@ -208,6 +240,13 @@ impl std::fmt::Display for BinaryOp { } } +/// 一元运算符 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum UnaryOp { + Not, + Neg, +} + impl std::fmt::Display for UnaryOp { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { @@ -217,6 +256,30 @@ impl std::fmt::Display for UnaryOp { } } +/// 语句 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum Statement { + // 表达式语句 + Expression(Expression), + + // 返回语句 + Return(Expression), + + // 变量声明 + Let { + name: String, + ty: Option, + value: Expression, + }, +} + +/// 测试块 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct TestBlock { + pub description: String, + pub assertions: Vec, +} + #[cfg(test)] mod tests { use super::*; @@ -227,6 +290,9 @@ mod tests { id: "XTZH_GOLD_COVERAGE".to_string(), level: ClauseLevel::Eternal, title: "黄金储备覆盖率底线".to_string(), + name: None, + version: None, + description: None, depends_on: vec![], parameters: vec![Parameter { name: "XTZH_GOLD_COVERAGE_MIN".to_string(), diff --git a/cnnl-compiler/src/parser/mod.rs b/cnnl-compiler/src/parser/mod.rs index e07d869..04977cd 100644 --- a/cnnl-compiler/src/parser/mod.rs +++ b/cnnl-compiler/src/parser/mod.rs @@ -1,5 +1,4 @@ pub mod ast; - pub use ast::*; use crate::lexer::{Lexer, Token}; use thiserror::Error; @@ -9,13 +8,10 @@ use thiserror::Error; pub enum ParserError { #[error("Unexpected token: expected {expected}, found {found}")] UnexpectedToken { expected: String, found: String }, - #[error("Unexpected end of file")] UnexpectedEof, - #[error("Invalid syntax: {message}")] InvalidSyntax { message: String }, - #[error("Lexer error: {0}")] LexerError(#[from] crate::lexer::LexerError), } @@ -33,7 +29,6 @@ impl<'source> Parser<'source> { let mut lexer = Lexer::new(source); let current = lexer.next().transpose()?; let peek = lexer.next().transpose()?; - Ok(Self { lexer, current, @@ -44,12 +39,23 @@ impl<'source> Parser<'source> { /// 解析整个程序 pub fn parse(&mut self) -> Result { let mut clauses = Vec::new(); - + let mut tests = Vec::new(); while self.current.is_some() { - clauses.push(self.parse_clause()?); + match &self.current { + Some(Token::Clause) => { + clauses.push(self.parse_clause()?); + } + Some(Token::Test) => { + tests.push(self.parse_test_block()?); + } + _ => { + return Err(ParserError::InvalidSyntax { + message: format!("Expected clause or test, found {:?}", self.current), + }); + } + } } - - Ok(Program { clauses }) + Ok(Program { clauses, tests }) } /// 解析条款 @@ -61,6 +67,9 @@ impl<'source> Parser<'source> { let mut level = ClauseLevel::Tactical; let mut title = String::new(); + let mut name: Option = None; + let mut version: Option = None; + let mut description: Option = None; let mut depends_on = Vec::new(); let mut parameters = Vec::new(); let mut predicates = Vec::new(); @@ -79,6 +88,25 @@ impl<'source> Parser<'source> { self.expect(Token::Colon)?; title = self.expect_string_literal()?; } + Some(Token::Name) => { + self.advance(); + self.expect(Token::Colon)?; + let n = self.expect_string_literal()?; + if title.is_empty() { + title = n.clone(); + } + name = Some(n); + } + Some(Token::Version) => { + self.advance(); + self.expect(Token::Colon)?; + version = Some(self.expect_string_literal()?); + } + Some(Token::Description) => { + self.advance(); + self.expect(Token::Colon)?; + description = Some(self.expect_string_literal()?); + } Some(Token::DependsOn) => { self.advance(); self.expect(Token::Colon)?; @@ -100,13 +128,15 @@ impl<'source> Parser<'source> { } } } - self.expect(Token::RBrace)?; Ok(Clause { id, level, title, + name, + version, + description, depends_on, parameters, predicates, @@ -145,7 +175,10 @@ impl<'source> Parser<'source> { let ty = self.parse_type()?; self.expect(Token::Assign)?; let value = self.parse_literal()?; - + // 可选分号 + if self.check(&Token::Semicolon) { + self.advance(); + } Ok(Parameter { name, ty, @@ -160,29 +193,23 @@ impl<'source> Parser<'source> { self.expect(Token::Predicate)?; let name = self.expect_ident()?; self.expect(Token::LParen)?; - let mut params = Vec::new(); while !self.check(&Token::RParen) { let param_name = self.expect_ident()?; self.expect(Token::Colon)?; let param_type = self.parse_type()?; params.push((param_name, param_type)); - if self.check(&Token::Comma) { self.advance(); } } - self.expect(Token::RParen)?; self.expect(Token::Arrow)?; let return_type = self.parse_type()?; self.expect(Token::LBrace)?; - // 简化:只解析单个返回表达式 let body = self.parse_expression()?; - self.expect(Token::RBrace)?; - Ok(Predicate { name, params, @@ -201,6 +228,7 @@ impl<'source> Parser<'source> { let mut frequency = ObligationFrequency::OnDemand; let mut enforcer = String::new(); let mut penalty = String::new(); + let mut description: Option = None; while !self.check(&Token::RBrace) { match &self.current { @@ -219,18 +247,21 @@ impl<'source> Parser<'source> { self.expect(Token::Colon)?; penalty = self.expect_ident()?; } + Some(Token::Description) => { + self.advance(); + self.expect(Token::Colon)?; + description = Some(self.expect_string_literal()?); + } _ => { return Err(ParserError::InvalidSyntax { message: format!("Unexpected token in obligation: {:?}", self.current), }); } } - if self.check(&Token::Comma) { self.advance(); } } - self.expect(Token::RBrace)?; Ok(Obligation { @@ -238,6 +269,7 @@ impl<'source> Parser<'source> { frequency, enforcer, penalty, + description, }) } @@ -263,6 +295,50 @@ impl<'source> Parser<'source> { } } + /// 解析测试块 + fn parse_test_block(&mut self) -> Result { + // test "DESCRIPTION" { assert EXPR ; ... } + self.expect(Token::Test)?; + let description = self.expect_string_literal()?; + self.expect(Token::LBrace)?; + let mut assertions = Vec::new(); + while !self.check(&Token::RBrace) { + if self.check(&Token::Assert) { + self.advance(); + let expr_str = self.collect_until_semicolon()?; + assertions.push(expr_str); + } else { + return Err(ParserError::InvalidSyntax { + message: format!("Expected assert in test block, found {:?}", self.current), + }); + } + } + self.expect(Token::RBrace)?; + Ok(TestBlock { description, assertions }) + } + + /// 收集 token 直到分号 + fn collect_until_semicolon(&mut self) -> Result { + let mut tokens = Vec::new(); + loop { + match &self.current { + Some(Token::Semicolon) => { + self.advance(); + break; + } + Some(Token::RBrace) => { + break; + } + Some(t) => { + tokens.push(format!("{}", t)); + self.advance(); + } + None => break, + } + } + Ok(tokens.join(" ")) + } + /// 解析表达式(简化版) fn parse_expression(&mut self) -> Result { self.parse_comparison() @@ -271,7 +347,6 @@ impl<'source> Parser<'source> { /// 解析比较表达式 fn parse_comparison(&mut self) -> Result { let mut left = self.parse_term()?; - while let Some(token) = &self.current { let op = match token { Token::Eq => BinaryOp::Eq, @@ -282,7 +357,6 @@ impl<'source> Parser<'source> { Token::Ge => BinaryOp::Ge, _ => break, }; - self.advance(); let right = self.parse_term()?; left = Expression::Binary { @@ -291,21 +365,18 @@ impl<'source> Parser<'source> { right: Box::new(right), }; } - Ok(left) } /// 解析项 fn parse_term(&mut self) -> Result { let mut left = self.parse_factor()?; - while let Some(token) = &self.current { let op = match token { Token::Plus => BinaryOp::Add, Token::Minus => BinaryOp::Sub, _ => break, }; - self.advance(); let right = self.parse_factor()?; left = Expression::Binary { @@ -314,60 +385,80 @@ impl<'source> Parser<'source> { right: Box::new(right), }; } - Ok(left) } /// 解析因子 fn parse_factor(&mut self) -> Result { - let mut left = self.parse_primary()?; - + let mut left = self.parse_unary()?; while let Some(token) = &self.current { let op = match token { Token::Star => BinaryOp::Mul, Token::Slash => BinaryOp::Div, + Token::Percent => BinaryOp::Mod, _ => break, }; - self.advance(); - let right = self.parse_primary()?; + let right = self.parse_unary()?; left = Expression::Binary { op, left: Box::new(left), right: Box::new(right), }; } - Ok(left) } + /// 解析一元表达式 + fn parse_unary(&mut self) -> Result { + match &self.current { + Some(Token::Not) => { + self.advance(); + let operand = self.parse_primary()?; + Ok(Expression::Unary { + op: UnaryOp::Not, + operand: Box::new(operand), + }) + } + Some(Token::Minus) => { + self.advance(); + let operand = self.parse_primary()?; + Ok(Expression::Unary { + op: UnaryOp::Neg, + operand: Box::new(operand), + }) + } + _ => self.parse_primary(), + } + } + /// 解析基本表达式 fn parse_primary(&mut self) -> Result { match &self.current { - Some(Token::IntLiteral(n)) => { - let n = *n; - self.advance(); - Ok(Expression::Literal(Literal::Int(n))) + Some(Token::IntLiteral(_)) + | Some(Token::FloatLiteral(_)) + | Some(Token::BoolLiteral(_)) + | Some(Token::StringLiteral(_)) => { + let lit = self.parse_literal()?; + Ok(Expression::Literal(lit)) } - Some(Token::FloatLiteral(f)) => { - let f = *f; - self.advance(); - Ok(Expression::Literal(Literal::Float(f))) - } - Some(Token::BoolLiteral(b)) => { - let b = *b; - self.advance(); - Ok(Expression::Literal(Literal::Bool(b))) - } - Some(Token::StringLiteral(s)) => { - let s = s.clone(); - self.advance(); - Ok(Expression::Literal(Literal::String(s))) - } - Some(Token::Ident(name)) | Some(Token::ConstantIdent(name)) => { - let name = name.clone(); - self.advance(); - Ok(Expression::Variable(name)) + Some(Token::Ident(_)) | Some(Token::ConstantIdent(_)) => { + let name = self.expect_ident()?; + // 检查是否是函数调用 + if self.check(&Token::LParen) { + self.advance(); + let mut args = Vec::new(); + while !self.check(&Token::RParen) { + args.push(self.parse_expression()?); + if self.check(&Token::Comma) { + self.advance(); + } + } + self.expect(Token::RParen)?; + Ok(Expression::Call { name, args }) + } else { + Ok(Expression::Variable(name)) + } } Some(Token::LParen) => { self.advance(); @@ -397,6 +488,10 @@ impl<'source> Parser<'source> { self.advance(); Ok(Type::U32) } + Some(Token::U128) => { + self.advance(); + Ok(Type::U128) + } Some(Token::F64) => { self.advance(); Ok(Type::F64) @@ -446,15 +541,12 @@ impl<'source> Parser<'source> { fn parse_string_array(&mut self) -> Result, ParserError> { self.expect(Token::LBracket)?; let mut strings = Vec::new(); - while !self.check(&Token::RBracket) { strings.push(self.expect_string_literal()?); - if self.check(&Token::Comma) { self.advance(); } } - self.expect(Token::RBracket)?; Ok(strings) } @@ -546,16 +638,41 @@ mod tests { parameter XTZH_GOLD_COVERAGE_MIN: f64 = 1.25 } "#; - let mut parser = Parser::new(source).expect("Parser creation failed"); let program = parser.parse().expect("Parse failed"); - assert_eq!(program.clauses.len(), 1); assert_eq!(program.clauses[0].id, "XTZH_GOLD_COVERAGE"); assert_eq!(program.clauses[0].level, ClauseLevel::Eternal); assert_eq!(program.clauses[0].parameters.len(), 1); } + #[test] + fn test_parse_name_version() { + let source = r#" + clause CORE_GOVERNANCE { + name: "核心治理条款" + version: "1.0.0" + level: eternal + title: "核心治理" + parameter MAX_VALIDATORS: u32 = 100 + parameter MIN_STAKE: u128 = 1000000000000000000 + obligation VALIDATOR_REGISTRATION { + frequency: continuous + enforcer: ai + penalty: suspension + description: "验证者必须质押最小金额" + } + } + "#; + let mut parser = Parser::new(source).expect("Parser creation failed"); + let program = parser.parse().expect("Parse failed"); + assert_eq!(program.clauses.len(), 1); + assert_eq!(program.clauses[0].id, "CORE_GOVERNANCE"); + assert_eq!(program.clauses[0].name, Some("核心治理条款".to_string())); + assert_eq!(program.clauses[0].version, Some("1.0.0".to_string())); + assert_eq!(program.clauses[0].parameters.len(), 2); + } + #[test] fn test_parse_predicate() { let source = r#" @@ -567,11 +684,24 @@ mod tests { } } "#; - let mut parser = Parser::new(source).expect("Parser creation failed"); let program = parser.parse().expect("Parse failed"); - assert_eq!(program.clauses[0].predicates.len(), 1); assert_eq!(program.clauses[0].predicates[0].name, "check_value"); } + + #[test] + fn test_parse_test_block() { + let source = r#" + test "核心治理参数一致性" { + assert MAX_VALIDATORS > 0 ; + assert MIN_STAKE >= 1000000000000000000 ; + } + "#; + let mut parser = Parser::new(source).expect("Parser creation failed"); + let program = parser.parse().expect("Parse failed"); + assert_eq!(program.tests.len(), 1); + assert_eq!(program.tests[0].description, "核心治理参数一致性"); + assert_eq!(program.tests[0].assertions.len(), 2); + } } diff --git a/cnnl-compiler/src/semantic/obligation_validator.rs b/cnnl-compiler/src/semantic/obligation_validator.rs index 3b100d6..142c08d 100644 --- a/cnnl-compiler/src/semantic/obligation_validator.rs +++ b/cnnl-compiler/src/semantic/obligation_validator.rs @@ -124,6 +124,9 @@ mod tests { id: "TEST".to_string(), level: ClauseLevel::Eternal, title: "Test".to_string(), + name: None, + version: None, + description: None, parameters: vec![], predicates: vec![], obligations: vec![Obligation { @@ -131,6 +134,7 @@ mod tests { frequency: crate::parser::ObligationFrequency::Continuous, enforcer: "ai_system".to_string(), penalty: "suspension".to_string(), + description: None, }], depends_on: vec![], }; @@ -146,6 +150,9 @@ mod tests { id: "TEST".to_string(), level: ClauseLevel::Eternal, title: "Test".to_string(), + name: None, + version: None, + description: None, parameters: vec![], predicates: vec![], obligations: vec![Obligation { @@ -153,6 +160,7 @@ mod tests { frequency: crate::parser::ObligationFrequency::Continuous, enforcer: "".to_string(), penalty: "suspension".to_string(), + description: None, }], depends_on: vec![], }; @@ -168,6 +176,9 @@ mod tests { id: "TEST".to_string(), level: ClauseLevel::Eternal, title: "Test".to_string(), + name: None, + version: None, + description: None, parameters: vec![], predicates: vec![], obligations: vec![Obligation { @@ -175,6 +186,7 @@ mod tests { frequency: crate::parser::ObligationFrequency::Continuous, enforcer: "manual".to_string(), penalty: "suspension".to_string(), + description: None, }], depends_on: vec![], }; diff --git a/cnnl-compiler/src/semantic/scope_resolver.rs b/cnnl-compiler/src/semantic/scope_resolver.rs index 390f771..c3b20c9 100644 --- a/cnnl-compiler/src/semantic/scope_resolver.rs +++ b/cnnl-compiler/src/semantic/scope_resolver.rs @@ -161,6 +161,7 @@ impl ScopeResolver { Expression::Literal(_) => { // 字面量不需要解析 } + crate::parser::Expression::Raw(_) => {} } } } @@ -255,6 +256,9 @@ mod tests { id: "TEST".to_string(), level: ClauseLevel::Eternal, title: "Test".to_string(), + name: None, + version: None, + description: None, parameters: vec![Parameter { name: "x".to_string(), ty: Type::U64, diff --git a/cnnl-compiler/src/semantic/type_checker.rs b/cnnl-compiler/src/semantic/type_checker.rs index 5a408da..626acc8 100644 --- a/cnnl-compiler/src/semantic/type_checker.rs +++ b/cnnl-compiler/src/semantic/type_checker.rs @@ -132,6 +132,7 @@ impl TypeChecker { Expression::Call { name: _, args: _ } => Type::Bool, Expression::If { .. } => Type::Bool, Expression::Block(_) => Type::Bool, + crate::parser::Expression::Raw(_) => Type::Bool, } } } @@ -155,6 +156,9 @@ mod tests { id: "TEST".to_string(), level: crate::parser::ClauseLevel::Eternal, title: "Test".to_string(), + name: None, + version: None, + description: None, parameters: vec![Parameter { name: "x".to_string(), ty: Type::U64, @@ -182,6 +186,9 @@ mod tests { id: "TEST".to_string(), level: crate::parser::ClauseLevel::Eternal, title: "Test".to_string(), + name: None, + version: None, + description: None, parameters: vec![Parameter { name: "x".to_string(), ty: Type::U64, diff --git a/cnnl-compiler/src/verification/constraint_generator.rs b/cnnl-compiler/src/verification/constraint_generator.rs index c2d81f3..128698e 100644 --- a/cnnl-compiler/src/verification/constraint_generator.rs +++ b/cnnl-compiler/src/verification/constraint_generator.rs @@ -95,6 +95,7 @@ impl ConstraintGenerator { Expression::Block(_) => { "true".to_string() // 简化处理 } + Expression::Raw(s) => s.clone(), } } @@ -137,6 +138,9 @@ mod tests { id: "TEST".to_string(), level: ClauseLevel::Eternal, title: "Test".to_string(), + name: None, + version: None, + description: None, parameters: vec![], predicates: vec![Predicate { name: "test_pred".to_string(), diff --git a/cnnl-service/Cargo.lock b/cnnl-service/Cargo.lock new file mode 100644 index 0000000..0f2c21f --- /dev/null +++ b/cnnl-service/Cargo.lock @@ -0,0 +1,2314 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "actix-codec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-sink", + "memchr", + "pin-project-lite", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "actix-http" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f860ee6746d0c5b682147b2f7f8ef036d4f92fe518251a3a35ffa3650eafdf0e" +dependencies = [ + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "base64", + "bitflags", + "brotli", + "bytes", + "bytestring", + "derive_more", + "encoding_rs", + "flate2", + "foldhash", + "futures-core", + "h2", + "http", + "httparse", + "httpdate", + "itoa", + "language-tags", + "local-channel", + "mime", + "percent-encoding", + "pin-project-lite", + "rand", + "sha1", + "smallvec", + "tokio", + "tokio-util", + "tracing", + "zstd", +] + +[[package]] +name = "actix-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "actix-router" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f8c75c51892f18d9c46150c5ac7beb81c95f78c8b83a634d49f4ca32551fe7" +dependencies = [ + "bytestring", + "cfg-if", + "http", + "regex", + "regex-lite", + "serde", + "tracing", +] + +[[package]] +name = "actix-rt" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92589714878ca59a7626ea19734f0e07a6a875197eec751bb5d3f99e64998c63" +dependencies = [ + "actix-macros", + "futures-core", + "tokio", +] + +[[package]] +name = "actix-server" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65064ea4a457eaf07f2fba30b4c695bf43b721790e9530d26cb6f9019ff7502" +dependencies = [ + "actix-rt", + "actix-service", + "actix-utils", + "futures-core", + "futures-util", + "mio", + "socket2 0.5.10", + "tokio", + "tracing", +] + +[[package]] +name = "actix-service" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e46f36bf0e5af44bdc4bdb36fbbd421aa98c79a9bce724e1edeb3894e10dc7f" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "actix-utils" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" +dependencies = [ + "local-waker", + "pin-project-lite", +] + +[[package]] +name = "actix-web" +version = "4.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff87453bc3b56e9b2b23c1cc0b1be8797184accf51d2abe0f8a33ec275d316bf" +dependencies = [ + "actix-codec", + "actix-http", + "actix-macros", + "actix-router", + "actix-rt", + "actix-server", + "actix-service", + "actix-utils", + "actix-web-codegen", + "bytes", + "bytestring", + "cfg-if", + "cookie", + "derive_more", + "encoding_rs", + "foldhash", + "futures-core", + "futures-util", + "impl-more", + "itoa", + "language-tags", + "log", + "mime", + "once_cell", + "pin-project-lite", + "regex", + "regex-lite", + "serde", + "serde_json", + "serde_urlencoded", + "smallvec", + "socket2 0.6.2", + "time", + "tracing", + "url", +] + +[[package]] +name = "actix-web-codegen" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" +dependencies = [ + "actix-router", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "brotli" +version = "8.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "bytestring" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "113b4343b5f6617e7ad401ced8de3cc8b012e73a594347c307b90db3e9271289" +dependencies = [ + "bytes", +] + +[[package]] +name = "cc" +version = "1.2.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "cnnl-compiler" +version = "0.1.0" +dependencies = [ + "anyhow", + "env_logger", + "hex", + "lalrpop", + "lalrpop-util", + "log", + "logos", + "serde", + "serde_json", + "sha3", + "thiserror", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "cookie" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "ena" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" +dependencies = [ + "log", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_filter" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "impl-more" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "jiff" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3e3d65f018c6ae946ab16e80944b97096ed73c35b221d1c478a6c81d8f57940" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17c2b211d863c7fde02cbea8a3c1a439b98e109286554f2860bdded7ff83818" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lalrpop" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" +dependencies = [ + "ascii-canvas", + "bit-set", + "ena", + "itertools", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax 0.8.10", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" + +[[package]] +name = "libc" +version = "0.2.182" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" + +[[package]] +name = "libredox" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "local-channel" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" +dependencies = [ + "futures-core", + "futures-sink", + "local-waker", +] + +[[package]] +name = "local-waker" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "logos" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c000ca4d908ff18ac99b93a062cb8958d331c3220719c52e77cb19cc6ac5d2c1" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc487311295e0002e452025d6b580b77bb17286de87b57138f3b5db711cded68" +dependencies = [ + "beef", + "fnv", + "proc-macro2", + "quote", + "regex-syntax 0.6.29", + "syn", +] + +[[package]] +name = "logos-derive" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbfc0d229f1f42d790440136d941afd806bc9e949e2bcb8faa813b0f00d1267e" +dependencies = [ + "logos-codegen", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "nac-cnnl-service" +version = "0.1.0" +dependencies = [ + "actix-rt", + "actix-web", + "anyhow", + "chrono", + "cnnl-compiler", + "env_logger", + "hex", + "log", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "num-conv" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "portable-atomic-util" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax 0.8.10", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.10", +] + +[[package]] +name = "regex-lite" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "siphasher" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.6.2", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/cnnl-service/Cargo.toml b/cnnl-service/Cargo.toml new file mode 100644 index 0000000..e3d98be --- /dev/null +++ b/cnnl-service/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "nac-cnnl-service" +version = "0.1.0" +edition = "2021" +authors = ["NAC Core Team "] +description = "CNNL HTTP Service - RESTful API for CNNL Compiler" + +[dependencies] +# HTTP 框架 +actix-web = "4" +actix-rt = "2" + +# 序列化 +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" + +# 错误处理 +thiserror = "1.0" +anyhow = "1.0" + +# 日志 +log = "0.4" +env_logger = "0.11" + +# 时间 +chrono = { version = "0.4", features = ["serde"] } +hex = "0.4" + +# CNNL 编译器库(本地路径) +cnnl-compiler = { path = "../cnnl-compiler" } + +[[bin]] +name = "nac-cnnl-service" +path = "src/main.rs" + +[profile.release] +opt-level = 3 +lto = true +codegen-units = 1 diff --git a/cnnl-service/src/main.rs b/cnnl-service/src/main.rs new file mode 100644 index 0000000..0ff365c --- /dev/null +++ b/cnnl-service/src/main.rs @@ -0,0 +1,432 @@ +//! NAC CNNL HTTP 服务 +//! +//! 将 CNNL 编译器封装为 RESTful HTTP API,供立法 IDE、宪法沙箱等工具调用。 +//! +//! # 接口列表 +//! - POST /api/v1/compile - 编译 CNNL 源代码 +//! - POST /api/v1/parse - 解析 CNNL 源代码(仅返回 AST) +//! - POST /api/v1/validate - 验证 CNNL 语法(不生成字节码) +//! - GET /api/v1/health - 健康检查 +//! - GET /api/v1/version - 版本信息 + +use actix_web::{web, App, HttpServer, HttpResponse, Responder, middleware}; +use serde::{Deserialize, Serialize}; +use std::time::Instant; +use chrono::Utc; +use log::{info, warn, error}; + +// ============================================================ +// 请求/响应数据结构 +// ============================================================ + +/// 编译请求 +#[derive(Debug, Deserialize)] +pub struct CompileRequest { + /// CNNL 源代码 + pub source: String, + /// 是否启用形式化验证 + #[serde(default)] + pub enable_verification: bool, + /// 是否生成调试信息 + #[serde(default)] + pub debug_info: bool, + /// 是否生成宪法状态文件 + #[serde(default = "default_true")] + pub generate_state: bool, +} + +fn default_true() -> bool { + true +} + +/// 解析请求 +#[derive(Debug, Deserialize)] +pub struct ParseRequest { + /// CNNL 源代码 + pub source: String, +} + +/// 验证请求 +#[derive(Debug, Deserialize)] +pub struct ValidateRequest { + /// CNNL 源代码 + pub source: String, +} + +/// 通用 API 响应 +#[derive(Debug, Serialize)] +pub struct ApiResponse { + pub success: bool, + pub data: Option, + pub error: Option, + pub timestamp: String, + pub duration_ms: u64, +} + +impl ApiResponse { + pub fn ok(data: T, duration_ms: u64) -> Self { + Self { + success: true, + data: Some(data), + error: None, + timestamp: Utc::now().to_rfc3339(), + duration_ms, + } + } + + pub fn err(msg: String, duration_ms: u64) -> ApiResponse { + ApiResponse { + success: false, + data: None, + error: Some(msg), + timestamp: Utc::now().to_rfc3339(), + duration_ms, + } + } +} + +/// 编译结果 +#[derive(Debug, Serialize)] +pub struct CompileResult { + /// 字节码(hex 编码) + pub bytecode_hex: String, + /// 字节码长度(字节) + pub bytecode_size: usize, + /// 宪法状态 JSON(可选) + pub state_json: Option, + /// 条款数量 + pub clause_count: usize, + /// 条款摘要 + pub clauses: Vec, +} + +/// 解析结果 +#[derive(Debug, Serialize)] +pub struct ParseResult { + /// 条款数量 + pub clause_count: usize, + /// 测试块数量 + pub test_count: usize, + /// 条款详情 + pub clauses: Vec, +} + +/// 验证结果 +#[derive(Debug, Serialize)] +pub struct ValidateResult { + /// 是否有效 + pub valid: bool, + /// 错误列表 + pub errors: Vec, + /// 警告列表 + pub warnings: Vec, + /// 条款数量 + pub clause_count: usize, +} + +/// 条款摘要 +#[derive(Debug, Serialize)] +pub struct ClauseSummary { + pub id: String, + pub level: String, + pub title: String, + pub parameter_count: usize, + pub predicate_count: usize, + pub obligation_count: usize, +} + +/// 条款详情 +#[derive(Debug, Serialize)] +pub struct ClauseDetail { + pub id: String, + pub level: String, + pub title: String, + pub name: Option, + pub version: Option, + pub description: Option, + pub depends_on: Vec, + pub parameters: Vec, + pub predicates: Vec, + pub obligations: Vec, +} + +/// 参数详情 +#[derive(Debug, Serialize)] +pub struct ParameterDetail { + pub name: String, + pub type_name: String, + pub value: String, + pub description: Option, +} + +/// 谓词详情 +#[derive(Debug, Serialize)] +pub struct PredicateDetail { + pub name: String, + pub params: Vec<(String, String)>, + pub return_type: String, +} + +/// 义务详情 +#[derive(Debug, Serialize)] +pub struct ObligationDetail { + pub name: String, + pub frequency: String, + pub enforcer: String, + pub penalty: String, + pub description: Option, +} + +/// 版本信息 +#[derive(Debug, Serialize)] +pub struct VersionInfo { + pub service: String, + pub version: String, + pub compiler_version: String, + pub build_time: String, +} + +/// 健康状态 +#[derive(Debug, Serialize)] +pub struct HealthStatus { + pub status: String, + pub uptime_seconds: u64, +} + +// ============================================================ +// 全局状态 +// ============================================================ + +pub struct AppState { + pub start_time: Instant, +} + +// ============================================================ +// API 处理函数 +// ============================================================ + +/// POST /api/v1/compile - 编译 CNNL 源代码 +async fn handle_compile( + state: web::Data, + req: web::Json, +) -> impl Responder { + let start = Instant::now(); + info!("收到编译请求,源代码长度: {} 字节", req.source.len()); + + let options = cnnl_compiler::CompilerOptions { + enable_verification: req.enable_verification, + debug_info: req.debug_info, + output_dir: None, + generate_state_file: req.generate_state, + }; + + match cnnl_compiler::compile(&req.source, options) { + Ok(result) => { + let bytecode_hex = hex::encode(&result.bytecode); + let state_json = result.state_json.as_ref().and_then(|s| { + serde_json::from_str(s).ok() + }); + let clauses: Vec = result.ast.clauses.iter().map(|c| ClauseSummary { + id: c.id.clone(), + level: c.level.to_string(), + title: c.title.clone(), + parameter_count: c.parameters.len(), + predicate_count: c.predicates.len(), + obligation_count: c.obligations.len(), + }).collect(); + let clause_count = clauses.len(); + let compile_result = CompileResult { + bytecode_hex, + bytecode_size: result.bytecode.len(), + state_json, + clause_count, + clauses, + }; + let duration_ms = start.elapsed().as_millis() as u64; + info!("编译成功,字节码大小: {} 字节,耗时: {}ms", compile_result.bytecode_size, duration_ms); + HttpResponse::Ok().json(ApiResponse::ok(compile_result, duration_ms)) + } + Err(e) => { + let duration_ms = start.elapsed().as_millis() as u64; + warn!("编译失败: {}", e); + HttpResponse::BadRequest().json(ApiResponse::::err( + format!("{}", e), + duration_ms, + )) + } + } +} + +/// POST /api/v1/parse - 解析 CNNL 源代码 +async fn handle_parse( + _state: web::Data, + req: web::Json, +) -> impl Responder { + let start = Instant::now(); + info!("收到解析请求,源代码长度: {} 字节", req.source.len()); + + match cnnl_compiler::Parser::new(&req.source) { + Ok(mut parser) => { + match parser.parse() { + Ok(ast) => { + let clauses: Vec = ast.clauses.iter().map(|c| ClauseDetail { + id: c.id.clone(), + level: c.level.to_string(), + title: c.title.clone(), + name: c.name.clone(), + version: c.version.clone(), + description: c.description.clone(), + depends_on: c.depends_on.clone(), + parameters: c.parameters.iter().map(|p| ParameterDetail { + name: p.name.clone(), + type_name: p.ty.to_string(), + value: format!("{}", p.value), + description: p.description.clone(), + }).collect(), + predicates: c.predicates.iter().map(|pred| PredicateDetail { + name: pred.name.clone(), + params: pred.params.iter().map(|(n, t)| (n.clone(), t.to_string())).collect(), + return_type: pred.return_type.to_string(), + }).collect(), + obligations: c.obligations.iter().map(|o| ObligationDetail { + name: o.name.clone(), + frequency: format!("{:?}", o.frequency), + enforcer: o.enforcer.clone(), + penalty: o.penalty.clone(), + description: o.description.clone(), + }).collect(), + }).collect(); + let test_count = ast.tests.len(); + let clause_count = clauses.len(); + let parse_result = ParseResult { + clause_count, + test_count, + clauses, + }; + let duration_ms = start.elapsed().as_millis() as u64; + info!("解析成功,条款数: {},测试块数: {},耗时: {}ms", clause_count, test_count, duration_ms); + HttpResponse::Ok().json(ApiResponse::ok(parse_result, duration_ms)) + } + Err(e) => { + let duration_ms = start.elapsed().as_millis() as u64; + warn!("解析失败: {}", e); + HttpResponse::BadRequest().json(ApiResponse::::err( + format!("{}", e), + duration_ms, + )) + } + } + } + Err(e) => { + let duration_ms = start.elapsed().as_millis() as u64; + warn!("词法分析失败: {}", e); + HttpResponse::BadRequest().json(ApiResponse::::err( + format!("{}", e), + duration_ms, + )) + } + } +} + +/// POST /api/v1/validate - 验证 CNNL 语法 +async fn handle_validate( + _state: web::Data, + req: web::Json, +) -> impl Responder { + let start = Instant::now(); + info!("收到验证请求,源代码长度: {} 字节", req.source.len()); + + let mut errors = Vec::new(); + let warnings = Vec::new(); + let mut clause_count = 0; + + match cnnl_compiler::Parser::new(&req.source) { + Ok(mut parser) => { + match parser.parse() { + Ok(ast) => { + clause_count = ast.clauses.len(); + // 语义分析 + let mut analyzer = cnnl_compiler::semantic::SemanticAnalyzer::new(); + if let Err(e) = analyzer.analyze(&ast) { + errors.push(format!("语义错误: {}", e)); + } + } + Err(e) => { + errors.push(format!("语法错误: {}", e)); + } + } + } + Err(e) => { + errors.push(format!("词法错误: {}", e)); + } + } + + let valid = errors.is_empty(); + let validate_result = ValidateResult { + valid, + errors, + warnings, + clause_count, + }; + let duration_ms = start.elapsed().as_millis() as u64; + info!("验证完成,有效: {},耗时: {}ms", valid, duration_ms); + HttpResponse::Ok().json(ApiResponse::ok(validate_result, duration_ms)) +} + +/// GET /api/v1/health - 健康检查 +async fn handle_health(state: web::Data) -> impl Responder { + let uptime_seconds = state.start_time.elapsed().as_secs(); + let health = HealthStatus { + status: "ok".to_string(), + uptime_seconds, + }; + HttpResponse::Ok().json(ApiResponse::ok(health, 0)) +} + +/// GET /api/v1/version - 版本信息 +async fn handle_version(_state: web::Data) -> impl Responder { + let version = VersionInfo { + service: "nac-cnnl-service".to_string(), + version: env!("CARGO_PKG_VERSION").to_string(), + compiler_version: "0.1.0".to_string(), + build_time: env!("CARGO_PKG_VERSION").to_string(), + }; + HttpResponse::Ok().json(ApiResponse::ok(version, 0)) +} + +// ============================================================ +// 主函数 +// ============================================================ + +#[actix_web::main] +async fn main() -> std::io::Result<()> { + env_logger::init_from_env(env_logger::Env::default().default_filter_or("info")); + + let host = std::env::var("CNNL_HOST").unwrap_or_else(|_| "0.0.0.0".to_string()); + let port: u16 = std::env::var("CNNL_PORT") + .unwrap_or_else(|_| "8080".to_string()) + .parse() + .unwrap_or(8080); + + info!("NAC CNNL HTTP 服务启动中..."); + info!("监听地址: {}:{}", host, port); + + let app_state = web::Data::new(AppState { + start_time: Instant::now(), + }); + + HttpServer::new(move || { + App::new() + .app_data(app_state.clone()) + .app_data(web::JsonConfig::default().limit(1024 * 1024)) // 1MB 请求体限制 + // API 路由 + .route("/api/v1/compile", web::post().to(handle_compile)) + .route("/api/v1/parse", web::post().to(handle_parse)) + .route("/api/v1/validate", web::post().to(handle_validate)) + .route("/api/v1/health", web::get().to(handle_health)) + .route("/api/v1/version", web::get().to(handle_version)) + }) + .bind(format!("{}:{}", host, port))? + .run() + .await +}