iii/
lib.rs

1use std::fs::File;
2use std::io::{Write, BufReader, BufRead};
3
4/// ### The databuf store kv data
5/// ```rust
6/// use iii::BufData;
7/// let mut cc = BufData::new();
8/// cc.chgvalue("c3", "ccc3");
9/// cc.chgvalue("c5", "5c");
10/// if let Some(v) = cc.getvalue("c3"){
11///     println!("K:{},V:{}","c3",v);
12/// }
13/// cc.save(None);
14/// ```
15#[derive(Default)]
16pub struct BufData{
17    filepath:String,
18    data:Vec<DataType>,
19}
20enum DataType {
21    Notes(String),
22    Data((String,String)),
23}
24
25impl BufData {
26    /// Create a empty data squence in memory
27    pub fn new()->Self{
28        Self { filepath:"default.iii".to_string(),..Default::default() }
29    }
30    /// ### load config file
31    /// 
32    /// ```rust
33    /// use iii::BufData;
34    /// let mut cc = BufData::loadfromiii("default.iii");
35    /// ```
36    pub fn loadfromiii(filepath:&str)->Result<Self,&'static str>{
37        let mut data = Vec::new();
38        if let Ok(file)=File::open(filepath){
39            for idx in BufReader::new(file).lines(){
40                if let Ok(iidx) = idx{
41                    if iidx.trim().starts_with("#"){
42                        data.push(DataType::Notes(iidx));
43                    }else{
44                        let cc:Vec<&str> = iidx.trim().split("=").collect();
45                        if cc.len() == 2{
46                            data.push(DataType::Data((cc[0].trim().to_string(),cc[1].trim().to_string())));
47                        }
48                    }
49                }
50            }
51            Ok(Self{filepath:filepath.to_string(),data:data})
52        }else{
53            Err("load file fail")
54        }
55        
56    }
57    
58    fn onlywrite(&self,path:&str)->Result<(),&'static str>{
59        if let Ok(mut f) = File::create(path){
60            let mut bufstr = String::new();
61            for idx in &self.data{
62                match idx {
63                    DataType::Data((s1,s2))=>{
64                        bufstr.push_str(&format!("{} = {}\r\n",s1,s2));
65                    },
66                    DataType::Notes(commet)=>{
67                        bufstr.push_str(&commet);
68                        bufstr.push_str("\r\n");
69                    },
70                }
71            }
72            if let Ok(_) = f.write(bufstr.as_bytes()){
73                return Ok(());
74            }
75        }
76        Err("write err")
77
78    }
79    
80    /// ### save config to file 
81    /// if newfile is None,use loaded file's path to save 
82    /// 
83    /// ```rust
84    /// use iii::BufData;
85    /// if let Ok(mut cc) = BufData::loadfromiii("default.iii"){
86    ///     cc.chgvalue("c3", "ccc3");
87    ///     cc.chgvalue("c5", "5c");
88    ///     if let Ok(_) = cc.save(None){
89    ///         println!("file write success")
90    ///     };
91    ///     if let Ok(_) = cc.save(Some("file1.iii")){
92    ///         println!("file1.iii write success")
93    ///     }
94    /// }
95    /// ```
96    pub fn save(&self,newfilepath:Option<&str>)->Result<(),&'static str>{
97        if let Some(pth) = newfilepath{
98            self.onlywrite(pth)
99        }else{
100            self.onlywrite(&self.filepath)
101        }
102    }
103    /// ### read value from file by key
104    /// ```rust
105    /// use iii::BufData;
106    /// if let Ok(cc) = BufData::loadfromiii("default.iii"){
107    ///     cc.chgvalue("c2", "33");
108    ///     cc.chgvalue("c4", &true.to_string());
109    ///     let Ok(value) = cc.getvalue1::<u32>("c2").unwrap();
110    ///     assert!(33==value);
111    ///     let Ok(value) = cc.getvalue1::<bool>("c4").unwrap();
112    ///     assert!(true==value);
113    /// };
114    /// ```
115    pub fn getvalue<T: std::str::FromStr>(&self,key:&str)->Result<T,()>{
116        for idx in &self.data{
117            if let DataType::Data((s1,s2))=idx{
118                if &key.to_string() == s1{
119                    if let Ok(ss) = s2.parse::<T>(){
120                        return Ok(ss);
121                    }
122                }
123            }
124        }
125        return Err(());
126    }
127    /// ### write value or change value
128    /// ```rust
129    /// use iii::BufData;
130    /// if let Ok(mut cc) = BufData::loadfromiii("default.iii"){
131    ///     cc.chgvalue("c3", "ccc3");
132    ///     cc.chgvalue("c5", 233);
133    ///     if let Ok(_) = cc.save(None){
134    ///         println!("file write success")
135    ///     };
136    /// };
137    /// ```
138    pub fn chgvalue<T:std::fmt::Display>(&mut self,key:&str,value:T){
139        for idx in &mut self.data{
140            if let DataType::Data((s1,s2))=idx{
141                if &key.to_string() == s1{
142                    s2.clear();
143                    s2.push_str(&value.to_string());
144                    return;
145                }
146            }
147        }
148        self.data.push(DataType::Data((key.to_string(),value.to_string())));
149    }
150}
151
152#[cfg(test)]
153mod tests {
154    use super::*;
155
156    #[test]
157    fn crate1(){
158        let mut cc = BufData::new();
159        cc.chgvalue("c1", "value");
160        cc.chgvalue("c2", "value2");
161        cc.chgvalue("c3", "value3");
162        if let Ok(_) = cc.save(None){
163            println!("file write success")
164        };
165    }
166    #[test]
167    fn readwrite(){
168        if let Ok(mut cc) = BufData::loadfromiii("default.iii"){
169            cc.chgvalue("c3", "ccc3");
170            cc.chgvalue("c5", "5c");
171            if let Ok(_) = cc.save(None){
172                println!("file write success")
173            };
174        };
175    }
176
177    #[test]
178    fn readvalue(){
179        if let Ok(cc) = BufData::loadfromiii("default.iii"){
180            if let Ok(v) = cc.getvalue::<String>("c2"){
181                println!("K:{},V:{}","c2",v);
182            }
183            if let Ok(v) = cc.getvalue::<String>("c5"){
184                println!("K:{},V:{}","c5",v);
185            }
186        };
187    }
188    #[test]
189    fn getnumbervalue()->Result<(),()>{
190        let mut cc = BufData::new();
191        cc.chgvalue("c2", "33");
192        cc.chgvalue("c4", &true.to_string());
193        let Ok(value) = cc.getvalue::<u32>("c2") else {return Err(())};
194        assert!(33==value);
195        let Ok(value) = cc.getvalue::<bool>("c4") else {return Err(());};
196        assert!(true==value);
197        Ok(())
198    }
199}