Skip to content

Commit 0cc66f2

Browse files
committed
Initial commit
1 parent 3128d8b commit 0cc66f2

17 files changed

+1615
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
/Cargo.lock

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[workspace]
2+
members = ["tsap", "tsap_macro", "tests"]

tests/Cargo.toml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "tsap_tests"
3+
version = "0.0.0"
4+
authors = ["Lorenz Schmidt <[email protected]>"]
5+
edition = "2021"
6+
publish = false
7+
8+
[dependencies]
9+
tsap = { path = "../tsap" }
10+
11+
[dev-dependencies]
12+
macrotest = "=1.0.9"
13+
trybuild = "1.0"

tests/tests/expandtest.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#[test]
2+
pub fn expandtest() {
3+
macrotest::expand("tests/expand/*.rs");
4+
}

tests/tests/uitest.rs

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#[test]
2+
fn ui() {
3+
let t = trybuild::TestCases::new();
4+
t.compile_fail("tests/ui/*.rs");
5+
}

tsap/Cargo.toml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[package]
2+
name = "tsap"
3+
version = "0.1.0"
4+
edition = "2018"
5+
6+
[[bin]]
7+
name = "example"
8+
path = "src/example.rs"
9+
10+
[dependencies]
11+
thiserror = "1.0"
12+
tsap_macro = { version = "0.1.0", path = "../tsap_macro" }
13+
toml = { version = "0.5", optional = true }
14+
serde = { version = "1.0", optional = true, features = ["derive"] }
15+
glob = "0.3"
16+
17+
[features]
18+
default = ["toml"]
19+
toml = ["dep:serde", "dep:toml"]

tsap/src/error.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use thiserror::Error;
2+
3+
pub type Result<T> = std::result::Result<T, Error>;
4+
5+
#[derive(Error, Debug)]
6+
pub enum Error {
7+
#[cfg(feature = "toml")]
8+
#[error("could not parse configuration")]
9+
TomlParse(#[from] toml::de::Error),
10+
#[cfg(feature = "toml")]
11+
#[error("invalid key path")]
12+
InvalidPath(String),
13+
#[error("invalid argument")]
14+
InvalidArg(String),
15+
#[error("merging dictionaries failed")]
16+
MergeFailed,
17+
#[error("key {0} does not exist in {1}")]
18+
KeyNotExists(String, String),
19+
#[error("parameter violates constrain: {0}")]
20+
InvalidParam(String),
21+
#[error("input/output error")]
22+
Io {
23+
#[from]
24+
source: std::io::Error,
25+
},
26+
}

tsap/src/example.rs

+187
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
#![feature(try_trait_v2)]
2+
3+
use tsap::{param, ParamGuard, Call};
4+
5+
/*
6+
#[param]
7+
#[derive(Debug)]
8+
pub struct SVClassifier {
9+
nu: f32
10+
}
11+
12+
impl ParamGuard for SVClassifier {
13+
type Error = tsap::Error;
14+
15+
fn check(&self) -> Result<(), Self::Error> {
16+
if self.nu < 0.0 {
17+
return Err(tsap::Error::InvalidParam(
18+
format!("SV classifier regularization should be positive, but {}", self.nu)
19+
));
20+
}
21+
22+
Ok(())
23+
}
24+
}
25+
26+
impl Default for SVClassifier {
27+
fn default() -> Self {
28+
SVClassifier {
29+
nu: 100.0,
30+
}
31+
}
32+
}
33+
34+
#[param]
35+
#[derive(Debug)]
36+
pub enum ModelParam {
37+
RandomForest {
38+
ntrees: usize
39+
},
40+
SVClassifier(SVClassifier),
41+
}
42+
43+
impl From<SVClassifier> for Call<ModelParam> {
44+
fn from(val: SVClassifier) -> Self {
45+
Call::from(ModelParam::SVClassifier(val))
46+
}
47+
}
48+
49+
impl ParamGuard for ModelParam {
50+
type Error = tsap::Error;
51+
}
52+
*/
53+
54+
//#[param]
55+
//pub enum Param<const C: bool> {
56+
// Blub(Param2<C, C>, u32),
57+
// Bla
58+
//}
59+
//#[param]
60+
//#[derive(Debug)]
61+
//pub struct SVClassifier<const C: bool> {
62+
// nu: f32
63+
//}
64+
//
65+
//impl<const C: bool> ParamGuard for SVClassifier<C> {
66+
// type Error = tsap::Error;
67+
//
68+
// fn check(&self) -> Result<(), Self::Error> {
69+
// Ok(())
70+
// }
71+
//}
72+
//
73+
//impl Default for SVClassifier<true> {
74+
// fn default() -> Self {
75+
// SVClassifier {
76+
// nu: 0.1
77+
// }
78+
// }
79+
//}
80+
//
81+
//#[param]
82+
//#[derive(Debug)]
83+
//pub enum Model<const C: bool> {
84+
// SVClassifier(SVClassifier<C>),
85+
//}
86+
//
87+
//impl Default for Model<true> {
88+
// fn default() -> Self {
89+
// Model::SVClassifier(SVClassifier::default())
90+
// }
91+
//}
92+
//
93+
//impl<const C: bool> ParamGuard for Model<C> {
94+
// type Error = tsap::Error;
95+
//
96+
// fn check(&self) -> Result<(), Self::Error> {
97+
// Ok(())
98+
// }
99+
//}
100+
101+
#[param]
102+
#[derive(Debug)]
103+
pub struct Param<const C: bool, T: Default> {
104+
seed: T,
105+
//model: Model<C>,
106+
//rev: String,
107+
//date: String,
108+
109+
//model: ModelParam,
110+
}
111+
112+
impl<T: Default> Default for Param<true, T> {
113+
fn default() -> Self {
114+
Param {
115+
seed: T::default()
116+
//rev: "Blub".into(),
117+
//date: "null".into(),
118+
//model: ModelParam::RandomForest { ntrees: 10 }
119+
}
120+
}
121+
}
122+
123+
impl<const C: bool, T: Default> ParamGuard for Param<C, T> {
124+
type Error = tsap::Error;
125+
126+
fn check(&self) -> Result<(), Self::Error> {
127+
Ok(())
128+
}
129+
}
130+
fn main() -> Result<(), tsap::Error> {
131+
let param = Param::default()
132+
.seed(|x| x+1)?;
133+
134+
Ok(())
135+
}
136+
137+
/*
138+
139+
140+
141+
fn main() -> Result<(), tsap::Error> {
142+
let p = Param::default()
143+
.seed(100)
144+
.build()?
145+
.seed(|x| x+1)
146+
//.try_seed(|x| Ok(x + 1000))
147+
.model(|x| x.svclassifier(|x| x.nu(10.0)))
148+
// do we really need a Box<TryInto<SVClassifierParam>> here? Distinction between Param and
149+
// ParamBuilder not easy to make, but how plays this together with trait bound on return
150+
// value
151+
//.try_model(|x| x.try_svclassifier(|x| x.nu(10.0)))
152+
//.model(|obj| obj.nu(1000.0).build()?)
153+
//.model(ModelParam::SVClassifier { nu: 100.0 })
154+
.build()?;
155+
156+
Ok(())
157+
}*/
158+
159+
/*fn main() -> Result<(), tsap::Error> {
160+
let p = Param::from(toml::toml!(
161+
rev = { cmd = "git rev-parse --short HEAD" }
162+
date = { cmd = "date '+%d-%m-%Y %H:%M:%S'" }
163+
seed = 100
164+
165+
[model]
166+
from_file = { base_path = "config/models/", default = "randomforest" }
167+
));
168+
169+
dbg!(&p.0.root);
170+
171+
let p = Param::from_file("config/main.toml")?
172+
.seed(50)
173+
.seed(|x| x+3)
174+
.seed(|x| x+3)
175+
.amend_file("config/main.toml")?;
176+
177+
dbg!(&p.get_seed());
178+
179+
let p: Param = p.try_into()?;
180+
181+
dbg!(&p);
182+
183+
Ok(())
184+
}*/
185+
186+
//https://ferrous-systems.com/blog/testing-proc-macros/
187+
//https://github.com/ferrous-systems/testing-proc-macros/blob/main/src/lib.rs

tsap/src/lib.rs

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
extern crate tsap_macro;
2+
3+
pub use tsap_macro::param;
4+
5+
#[cfg(feature = "toml")]
6+
pub mod toml_builder;
7+
#[cfg(feature = "toml")]
8+
pub mod templates;
9+
10+
mod error;
11+
12+
pub use error::{Result, Error};
13+
pub use toml_builder::TomlBuilder;
14+
15+
pub trait ParamGuard {
16+
type Error;
17+
18+
fn check(&self) -> std::result::Result<(), Self::Error> {
19+
Ok(())
20+
}
21+
}
22+
23+
/// Caller semantic to accept owned values and closures in builder pattern
24+
pub struct Call<T>(Box<dyn FnOnce(T) -> T>);
25+
26+
impl<T> Call<T> {
27+
pub fn call(self, val: T) -> T {
28+
self.0(val)
29+
}
30+
}
31+
32+
//impl<T: 'static> From<T> for Call<T> {
33+
// fn from(val: T) -> Call<T> {
34+
// Call(Box::new(move |_| val))
35+
// }
36+
//}
37+
38+
impl<F: 'static, T> From<F> for Call<T> where F: FnOnce(T) -> T {
39+
fn from(val: F) -> Call<T> {
40+
Call(Box::new(val))
41+
}
42+
}
43+
//impl<F: 'static> From<F> for Call<usize> where F: FnOnce(usize) -> usize {
44+
// fn from(val: F) -> Call<usize> {
45+
// Call(Box::new(val))
46+
// }
47+
//}
48+
//
49+
//impl<F: 'static> From<F> for Call<f64> where F: FnOnce(f64) -> f64 {
50+
// fn from(val: F) -> Call<f64> {
51+
// Call(Box::new(val))
52+
// }
53+
//}
54+
55+
/// Caller semantic to accept owned values and closures in builder pattern
56+
pub struct TryCall<T>(Box<dyn FnOnce(T) -> Result<T>>);
57+
58+
impl<T> TryCall<T> {
59+
pub fn call(self, val: T) -> Result<T> {
60+
self.0(val)
61+
}
62+
}
63+
64+
impl<T: 'static> From<Result<T>> for TryCall<T> {
65+
fn from(val: Result<T>) -> TryCall<T> {
66+
TryCall(Box::new(move |_| val))
67+
}
68+
}
69+
70+
impl<F: 'static> From<F> for TryCall<usize> where F: FnOnce(usize) -> Result<usize> {
71+
fn from(val: F) -> TryCall<usize> {
72+
TryCall(Box::new(val))
73+
}
74+
}
75+
76+
impl<F: 'static> From<F> for TryCall<f64> where F: FnOnce(f64) -> Result<f64> {
77+
fn from(val: F) -> TryCall<f64> {
78+
TryCall(Box::new(val))
79+
}
80+
}

0 commit comments

Comments
 (0)