krabka_sdk_conformance/
vectors.rs1use std::{path::Path, str::FromStr};
4
5use serde::{Deserialize, Serialize};
6
7use crate::protocol::{Command, Response};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
11pub struct ContractVersion {
12 pub major: u16,
14 pub minor: u16,
16}
17
18impl ContractVersion {
19 #[must_use]
21 pub const fn new(major: u16, minor: u16) -> Self {
22 Self { major, minor }
23 }
24
25 #[must_use]
27 pub fn satisfies(self, vector: &Vector) -> bool {
28 if self < vector.since {
29 return false;
30 }
31 if let Some(until) = vector.until {
32 return self <= until;
33 }
34 true
35 }
36}
37
38#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
40pub struct Vector {
41 pub id: String,
43 pub since: ContractVersion,
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub until: Option<ContractVersion>,
48 #[serde(default)]
50 pub live_only: bool,
51 pub steps: Vec<VectorStep>,
53}
54
55#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
57pub struct VectorStep {
58 pub name: String,
60 pub command: Command,
62 pub expect: Response,
64}
65
66pub fn load_vectors(dir: impl AsRef<Path>) -> Result<Vec<Vector>, VectorError> {
73 let dir = dir.as_ref();
74 let mut entries = std::fs::read_dir(dir)?
75 .map(|entry| entry.map(|entry| entry.path()))
76 .collect::<Result<Vec<_>, _>>()?;
77 entries.sort();
78 let mut vectors = Vec::with_capacity(entries.len());
79 for path in entries {
80 if path.extension().and_then(std::ffi::OsStr::to_str) != Some("json") {
81 continue;
82 }
83 let text = std::fs::read_to_string(&path)?;
84 let vector =
85 serde_json::from_str::<Vector>(&text).map_err(|source| VectorError::JsonFile {
86 path: path.clone(),
87 source,
88 })?;
89 vectors.push(vector);
90 }
91 Ok(vectors)
92}
93
94pub fn parse_vector(text: &str) -> Result<Vector, serde_json::Error> {
100 serde_json::from_str(text)
101}
102
103#[derive(Debug, thiserror::Error)]
105#[non_exhaustive]
106pub enum VectorError {
107 #[error("vector io: {0}")]
109 Io(#[from] std::io::Error),
110 #[error("vector json in {}: {source}", path.display())]
112 JsonFile {
113 path: std::path::PathBuf,
115 source: serde_json::Error,
117 },
118}
119
120impl FromStr for Vector {
121 type Err = serde_json::Error;
122
123 fn from_str(s: &str) -> Result<Self, Self::Err> {
124 serde_json::from_str(s)
125 }
126}