diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/schema.rs | 215 |
1 files changed, 18 insertions, 197 deletions
diff --git a/src/schema.rs b/src/schema.rs index 57210a3..556e625 100644 --- a/src/schema.rs +++ b/src/schema.rs | |||
@@ -7,16 +7,16 @@ use std::sync::Arc; | |||
7 | // use crate::validators; | 7 | // use crate::validators; |
8 | 8 | ||
9 | // In memory data structure | 9 | // In memory data structure |
10 | |||
11 | // Two approaches here | 10 | // Two approaches here |
12 | // 1. Db is a type | 11 | // 1. Db is a type pub type Db = Arc<RwLock<Vec<Ledger>>>; Ledger is a struct, we wrap the ledger |
13 | // pub type Db = Arc<RwLock<Vec<Ledger>>>; | 12 | // with arc + mutex in ledger() to access transactions we need to unwrap blocks as well, vice |
14 | // Ledger is a struct, we wrap the ledger with arc + mutex in ledger() | 13 | // versa |
15 | // to access transactions we need to unwrap blocks as well, vice versa | 14 | // |
15 | // 2. Db is a struct attributes are wrapped we can offload ::new() to it's member method blocks and | ||
16 | // transactions are accessible separately, which is the biggest pro | ||
16 | // | 17 | // |
17 | // 2. Db is a struct, attributes are wrapped | 18 | // 3. use an actual database (for blockchain and users this makes the most sense tbh but pending |
18 | // we can offload ::new() to it's member method | 19 | // transactions are perfectly fine in memory) |
19 | // blocks and transactions are accessible separately, which is the biggest pro | ||
20 | 20 | ||
21 | /// Creates a new database | 21 | /// Creates a new database |
22 | pub fn create_database() -> Db { | 22 | pub fn create_database() -> Db { |
@@ -50,199 +50,20 @@ pub struct Transaction { | |||
50 | } | 50 | } |
51 | 51 | ||
52 | /// A block that was proposed with `transaction_list` and `nonce` that made `hash` valid | 52 | /// A block that was proposed with `transaction_list` and `nonce` that made `hash` valid |
53 | #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] | 53 | /// https://serde.rs/container-attrs.html might be valueable to normalize the serialize/deserialize |
54 | /// conventions as these will be hashed | ||
55 | #[derive(Serialize, Deserialize, Debug)] | ||
54 | pub struct Block { | 56 | pub struct Block { |
57 | // TODO: transaction list should hold transaction hash values <09-04-21, yigit> // | ||
58 | // but do we link them somehow? (like a log of old transactions?) | ||
59 | // we can leave this as is and whenever we have a new block we _could_ just log it to file | ||
60 | // somewhere | ||
61 | // I want to keep this as a String vector because it makes things easier elsewhere | ||
55 | pub transaction_list: Vec<String>, // hashes of the transactions (or just "source" for now) | 62 | pub transaction_list: Vec<String>, // hashes of the transactions (or just "source" for now) |
56 | pub nonce: i32, | 63 | pub nonce: String, |
57 | pub timestamp: NaiveDateTime, | 64 | pub timestamp: NaiveDateTime, |
58 | pub hash: String, // future proof'd baby | 65 | pub hash: String, // future proof'd baby |
59 | } | 66 | } |
60 | 67 | ||
61 | // pub struct Ledger { | ||
62 | // // heh. also https://doc.rust-lang.org/std/collections/struct.LinkedList.html says Vec is generally faster | ||
63 | // blockchain: Vec<Block>, | ||
64 | // // every proposer can have _one_ pending transaction, a way to enforce this, String is proposer identifier | ||
65 | // pending_transactions: HashMap<String, Transaction>, | ||
66 | // } | ||
67 | |||
68 | // #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] | ||
69 | // #[serde(rename_all = "camelCase")] | ||
70 | // pub struct Game { | ||
71 | // pub id: u64, | ||
72 | // pub title: String, | ||
73 | // #[serde(with = "validators::validate_game_rating")] | ||
74 | // pub rating: u8, | ||
75 | // pub genre: Genre, | ||
76 | // pub description: Option<String>, | ||
77 | // pub release_date: NaiveDateTime, | ||
78 | // } | ||
79 | |||
80 | // #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] | ||
81 | // #[serde(rename_all = "SCREAMING_SNAKE_CASE")] | ||
82 | // pub enum Genre { | ||
83 | // RolePlaying, | ||
84 | // Strategy, | ||
85 | // Shooter, | ||
86 | // } | ||
87 | |||
88 | // #[derive(Deserialize, Debug, PartialEq)] | ||
89 | // pub struct ListOptions { | ||
90 | // pub offset: Option<usize>, | ||
91 | // pub limit: Option<usize>, | ||
92 | // } | ||
93 | |||
94 | // pub fn example_db() -> Db { | ||
95 | // Arc::new(Mutex::new( | ||
96 | // vec![ | ||
97 | // Game { | ||
98 | // id: 1, | ||
99 | // title: String::from("Dark Souls"), | ||
100 | // rating: 91, | ||
101 | // genre: Genre::RolePlaying, | ||
102 | // description: Some(String::from("Takes place in the fictional kingdom of Lordran, where players assume the role of a cursed undead character who begins a pilgrimage to discover the fate of their kind.")), | ||
103 | // release_date: NaiveDate::from_ymd(2011, 9, 22).and_hms(0, 0, 0), | ||
104 | // }, | ||
105 | // Game { | ||
106 | // id: 2, | ||
107 | // title: String::from("Dark Souls 2"), | ||
108 | // rating: 87, | ||
109 | // genre: Genre::RolePlaying, | ||
110 | // description: None, | ||
111 | // release_date: NaiveDate::from_ymd(2014, 3, 11).and_hms(0, 0, 0), | ||
112 | // }, | ||
113 | // Game { | ||
114 | // id: 3, | ||
115 | // title: String::from("Dark Souls 3"), | ||
116 | // rating: 89, | ||
117 | // genre: Genre::RolePlaying, | ||
118 | // description: Some(String::from("The latest chapter in the series with its trademark sword and sorcery combat and rewarding action RPG gameplay.")), | ||
119 | // release_date: NaiveDate::from_ymd(2016, 3, 24).and_hms(0, 0, 0), | ||
120 | // }, | ||
121 | // ] | ||
122 | // )) | ||
123 | // } | ||
124 | |||
125 | // TODO: these tests are amazing, we should write some when schema is decided upon <07-04-21, yigit> // | ||
126 | |||
127 | // #[cfg(test)] | ||
128 | // mod tests { | ||
129 | // use super::*; | ||
130 | |||
131 | // use serde_json::error::Error; | ||
132 | // use serde_test::{assert_tokens, Token}; | ||
133 | |||
134 | // #[test] | ||
135 | // fn game_serialize_correctly() { | ||
136 | // let game = Game { | ||
137 | // id: 1, | ||
138 | // title: String::from("Test"), | ||
139 | // rating: 90, | ||
140 | // genre: Genre::Shooter, | ||
141 | // description: None, | ||
142 | // release_date: NaiveDate::from_ymd(2019, 11, 12).and_hms(0, 0, 0), | ||
143 | // }; | ||
144 | |||
145 | // assert_tokens( | ||
146 | // &game, | ||
147 | // &[ | ||
148 | // Token::Struct { | ||
149 | // name: "Game", | ||
150 | // len: 6, | ||
151 | // }, | ||
152 | // Token::String("id"), | ||
153 | // Token::U64(1), | ||
154 | // Token::String("title"), | ||
155 | // Token::String("Test"), | ||
156 | // Token::String("rating"), | ||
157 | // Token::U8(90), | ||
158 | // Token::String("genre"), | ||
159 | // Token::UnitVariant { | ||
160 | // name: "Genre", | ||
161 | // variant: "SHOOTER", | ||
162 | // }, | ||
163 | // Token::String("description"), | ||
164 | // Token::None, | ||
165 | // Token::String("releaseDate"), | ||
166 | // Token::String("2019-11-12T00:00:00"), | ||
167 | // Token::StructEnd, | ||
168 | // ], | ||
169 | // ); | ||
170 | // } | ||
171 | |||
172 | // #[test] | ||
173 | // fn game_deserialize_correctly() { | ||
174 | // let data = r#"{"id":3,"title":"Another game","rating":65,"genre":"STRATEGY","description":null,"releaseDate":"2016-03-11T00:00:00"}"#; | ||
175 | // let game: Game = serde_json::from_str(data).unwrap(); | ||
176 | // let expected_game = Game { | ||
177 | // id: 3, | ||
178 | // title: String::from("Another game"), | ||
179 | // rating: 65, | ||
180 | // genre: Genre::Strategy, | ||
181 | // description: None, | ||
182 | // release_date: NaiveDate::from_ymd(2016, 3, 11).and_hms(0, 0, 0), | ||
183 | // }; | ||
184 | |||
185 | // assert_eq!(game, expected_game); | ||
186 | // } | ||
187 | |||
188 | // #[test] | ||
189 | // fn game_error_when_wrong_rating_passed() { | ||
190 | // let data = r#"{"id":3,"title":"Another game","rating":120,"genre":"STRATEGY","description":null,"releaseDate":"2016-03-11T00:00:00"}"#; | ||
191 | // let err: Error = serde_json::from_str::<Game>(data).unwrap_err(); | ||
192 | |||
193 | // assert_eq!(err.is_data(), true); | ||
194 | // } | ||
195 | |||
196 | // #[test] | ||
197 | // fn genre_serialize_correctly() { | ||
198 | // let genre = Genre::Shooter; | ||
199 | // assert_tokens( | ||
200 | // &genre, | ||
201 | // &[Token::UnitVariant { | ||
202 | // name: "Genre", | ||
203 | // variant: "SHOOTER", | ||
204 | // }], | ||
205 | // ); | ||
206 | |||
207 | // let genre = Genre::RolePlaying; | ||
208 | // assert_tokens( | ||
209 | // &genre, | ||
210 | // &[Token::UnitVariant { | ||
211 | // name: "Genre", | ||
212 | // variant: "ROLE_PLAYING", | ||
213 | // }], | ||
214 | // ); | ||
215 | |||
216 | // let genre = Genre::Strategy; | ||
217 | // assert_tokens( | ||
218 | // &genre, | ||
219 | // &[Token::UnitVariant { | ||
220 | // name: "Genre", | ||
221 | // variant: "STRATEGY", | ||
222 | // }], | ||
223 | // ); | ||
224 | // } | ||
225 | |||
226 | // #[test] | ||
227 | // fn genre_deserialize_correctly() { | ||
228 | // let data = r#""SHOOTER""#; | ||
229 | // let genre: Genre = serde_json::from_str(data).unwrap(); | ||
230 | // let expected_genre = Genre::Shooter; | ||
231 | |||
232 | // assert_eq!(genre, expected_genre); | ||
233 | |||
234 | // let data = r#""ROLE_PLAYING""#; | ||
235 | // let genre: Genre = serde_json::from_str(data).unwrap(); | ||
236 | // let expected_genre = Genre::RolePlaying; | ||
237 | |||
238 | // assert_eq!(genre, expected_genre); | ||
239 | // } | ||
240 | |||
241 | // #[test] | ||
242 | // fn genre_error_when_wrong_rating_passed() { | ||
243 | // let data = r#""SPORT""#; | ||
244 | // let err: Error = serde_json::from_str::<Genre>(data).unwrap_err(); | ||
245 | 68 | ||
246 | // assert_eq!(err.is_data(), true); | 69 | // TODO: write schema tests using the original repo <09-04-21, yigit> // |
247 | // } | ||
248 | // } | ||