sntl_migrate/
migration.rs1use std::fmt;
2use std::str::FromStr;
3
4use crate::error::Error;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum TxMode {
13 PerMigration,
14 None,
15}
16
17#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct Version(String);
23
24impl Version {
25 pub fn as_str(&self) -> &str {
26 &self.0
27 }
28
29 pub fn timestamp(&self) -> &str {
30 &self.0[..15]
31 }
32
33 pub fn name(&self) -> &str {
34 &self.0[16..]
35 }
36}
37
38impl fmt::Display for Version {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 f.write_str(&self.0)
41 }
42}
43
44impl FromStr for Version {
45 type Err = Error;
46
47 fn from_str(s: &str) -> Result<Self, Self::Err> {
48 if s.len() < 17 {
49 return Err(Error::InvalidName {
50 name: s.to_string(),
51 });
52 }
53 let date = &s[0..8];
54 let sep1 = &s[8..9];
55 let time = &s[9..15];
56 let sep2 = &s[15..16];
57 if !date.chars().all(|c| c.is_ascii_digit())
58 || sep1 != "_"
59 || !time.chars().all(|c| c.is_ascii_digit())
60 || sep2 != "_"
61 {
62 return Err(Error::InvalidName {
63 name: s.to_string(),
64 });
65 }
66 let name = &s[16..];
67 if name.is_empty()
68 || !name
69 .chars()
70 .all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_')
71 {
72 return Err(Error::InvalidName {
73 name: s.to_string(),
74 });
75 }
76 Ok(Self(s.to_string()))
77 }
78}
79
80#[derive(Debug, Clone)]
82pub struct Migration {
83 pub version: Version,
84 pub sql: String,
85 pub tx_mode: TxMode,
86}