1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
// pub mod default {}
/// to log your projects (custom)
/// 
/// # Use
/// To use the custom log, you need to use 3 steps.
/// At first you will create a new `Log`. (You can also create more than one log for different usage.)
/// 
/// Just to remind, dont forget to import the [`custom`](https://docs.rs/log_file/0.1.1/log_file/custom) mudule:
/// ```rust
/// use log_file::custom::*;
/// ```
/// Then go on with the creating the `Log`:
/// ```rust
/// // create Log
/// let mut log = Log::new(true, ':');
/// ```
/// The second step is to use it. In the following I just will show the different options:
/// ```rust
/// // with context as String
/// log.add("Titel 1",String::from("Context 1"));
/// 
/// // with context as &str
/// log.add_str("Titel 2","Context 2");
/// ```
/// If that is done, you can finaly save the log in the end. Here an example for this step:
/// ```rust
/// // save log
/// log.save("log.txt");
/// ```
/// And now you are done. Now, every time you run your project, the new log will overwrite the existing one, if the file name dosn't change.
pub mod custom {
    /// elements (entries) in the log
    pub struct LogElement {
        time_stamp  :   Option<std::time::SystemTime>,
        title       :   String,
        context     :   String
    }
    impl LogElement {
        /// creates new LogElement with context as `String`
        /// 
        /// # Example
        /// ```rust
        /// let example = LogElement::new("Test",String::from("Hello, world!", true));
        /// ```
        pub fn new(title : &str, context : String, time_stamp_on : bool) -> LogElement {
            LogElement {
                time_stamp  :   if time_stamp_on {
                    Option::Some(std::time::SystemTime::now())
                } else {
                    Option::None
                },
                title       :   String::from(title),
                context     :   context
            }
        }
        /// creates new LogElement with context as `&str`
        /// 
        /// # Example
        /// ```rust
        /// let example = LogElement::new_str("Test","Hello, world!", true);
        /// ```
        pub fn new_str(title : &str, context : &str, time_stamp_on : bool) -> LogElement {
            LogElement {
                time_stamp  :   if time_stamp_on {
                    Option::Some(std::time::SystemTime::now())
                } else {
                    Option::None
                },
                title       :   String::from(title),
                context     :   String::from(context)
            }
        }
        /// converts this struct `LogElement` to `String`
        /// 
        /// # Example
        /// ```rust
        /// let example = LogElement::new_str("Test","Hello, world!", true);
        /// 
        /// println!("{}",example.to_string(':',std::time::SystemTime::now()));
        /// ```
        /// output:
        /// ```
        /// [0:0:25:0]  Test    :   Hello, world!
        /// ```
        /// 
        /// # Panics
        /// Panics if the [`SystemTime`](https://doc.rust-lang.org/std/time/struct.SystemTime.html) is before the UNIX EPOCH.
        pub fn to_string(&self, seperator : &char, start : std::time::SystemTime) -> String {
            match self.time_stamp {
                Some(time)  =>  {
                    format!(
                        "[{}]\t{}\t{}\t{}",
                        match time.duration_since(start.clone()) {
                            Ok(n) => {
                                format!(
                                    "{}:{}:{}:{}",
                                    trim_to_1000(n.as_secs() as usize),
                                    trim_to_1000(n.as_millis() as usize),
                                    trim_to_1000(n.as_micros() as usize),
                                    trim_to_1000(n.as_nanos() as usize)
                                )
                            },
                            Err(_) => panic!("SystemTime before UNIX EPOCH!"),
                        },
                        &self.title,
                        seperator,
                        &self.context
                    )
                },
                None        =>  {
                    format!(
                        "{}\t{}\t{}",
                        &self.title,
                        seperator,
                        &self.context
                    )
                },
            }
        }
    }
    impl Clone for LogElement {
        fn clone(&self) -> LogElement {
            LogElement::new(&self.title.clone()[..], self.context.clone(), {
                match self.time_stamp {
                    Some(_)  =>  true,
                    None        =>  false
                }
            })
        }
    }
    /// The main struct for the custom log
    /// 
    /// # Example
    /// To use the custom log, you need to use 3 steps.
    /// At first you will create a new `Log`. (You can also create more than one log for different usage.)
    /// 
    /// Just to remind, dont forget to import the [`custom`](https://docs.rs/log_file/0.1.1/log_file/custom)
    /// ```rust
    /// use log_file::custom::*;
    /// ```
    /// Then go on with the creating the `Log`:
    /// ```rust
    ///     // create Log
    ///     let mut log = Log::new(true, ':');
    /// ```
    /// The second step is to use it. In the following I just will show the different options:
    /// ```rust
    /// // with context as String
    /// log.add("Titel 1",String::from("Context 1"));
    /// 
    /// // with context as &str
    /// log.add_str("Titel 2","Context 2");
    /// ```
    /// If that is done, you can finaly save the log in the end. Here an example for this step:
    /// ```rust
    /// // save log
    /// log.save("log.txt");
    /// ```
    /// And now you are done. Now, every time you run your project, the new log will overwrite the existing one, if the file name dosn't change.
    pub struct Log {
        time_stamp  :   bool,
        start_time  :   std::time::SystemTime,
        seperator   :   char,
        elements    :   Vec<LogElement>
    }
    impl Log {
        /// create a new log
        /// 
        /// # Example
        /// ```rust
        /// let example = Log::new(true, ':'));
        /// ```
        pub fn new(time_stamp_on : bool, seperate : char) -> Log {
            Log {
                time_stamp  :   time_stamp_on,
                start_time  :   std::time::SystemTime::now(),
                seperator   :   seperate,
                elements    :   Vec::new(),
            }
        }
        /// adding an element to this log with context as `String`
        /// 
        /// # Example
        /// ```rust
        /// let mut example = Log::new(true, ':'));
        /// example.add("Test",String::from("Hello, world!"));
        /// ```
        pub fn add(&mut self, titel : &str, context : String) {
            self.elements.push(LogElement::new(titel, context, self.time_stamp));
        }
        /// adding an element to this log with context as `&str`
        /// 
        /// # Example
        /// ```rust
        /// let mut example = Log::new(true, ':'));
        /// example.add_str("Test","Hello, world!");
        /// ```
        pub fn add_str(&mut self, titel : &str, context : &str) {
            self.elements.push(LogElement::new_str(titel, context, self.time_stamp));
        }
        /// saves the log in `file_name`
        /// 
        /// Creates file if it does not exist and overwrites it if it does exist.
        /// 
        /// # Note
        /// You have to give the whole file name as parameter. For example `foo.txt`. If you just give `foo` as file name, it will create a file without file type.
        /// 
        /// # Example
        /// ```rust
        /// use log_file::default_code::Log;
        /// 
        /// fn main() {
        ///     let example = Log::new(true, String::from(":"));
        ///     example.save("foo.txt");
        /// }
        /// ```
        pub fn save(&self, file_name : &str) {
            std::fs::File::create(file_name).expect("Unable to write file");
            std::fs::write(file_name, self.to_string()).expect("Unable to write file");
        }
        /// converts this struct `Log`
        /// 
        /// # Example
        /// ```rust
        /// use log_file::default_code::Log;
        /// 
        /// fn main() {
        ///     let example = Log::new(true, String::from(":"));
        ///     println!("{}",example.to_string());
        /// }
        /// ```
        /// output:
        /// ```batch
        /// 
        /// ```
        pub fn to_string(&self) -> String {
            // start value
            let mut value = String::new();

            // counter
            let mut count = 0_usize;

            // collect value
            for element in self.elements.iter() {
                let s : String = element.to_string(&self.seperator,self.start_time.clone());
                for c in s.chars() {
                    value.push(c);
                }
                if count < self.elements.len()-1 {
                    value.push('\n');
                }

                count += 1;
            }

            // return value
            return value;
        }
    }
    impl Clone for Log {
        fn clone(&self) -> Log {
            Log::new(self.time_stamp.clone(), self.seperator.clone())
        }
    }

    // function
    /// scale the parameter to a number lower than 1000
    /// 
    /// # Example
    /// ```rust
    /// let to_big = 12345_usize;
    /// println!("{}",trim_to_1000(to_big));
    /// ```
    /// output:
    /// ```batch
    /// 123
    /// ```
    fn trim_to_1000(n:usize) -> usize {
        let mut num = n;
        while num > 1000 {
            num /= 1000;
        }
        return num;
    }
}