├── .gitignore
├── .rustfmt.toml
├── Cargo.toml
├── README.md
├── example
├── Cargo.toml
├── docker-compose.yaml
├── fixtures
│ └── mariadb
│ │ └── schema.sql
├── src
│ ├── lib.rs
│ └── model.rs
└── tests
│ └── it_works.rs
├── img
└── meme.jpg
├── symbols-models
├── Cargo.toml
└── src
│ └── lib.rs
└── symbols
├── Cargo.toml
└── src
└── lib.rs
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | */target
3 | Cargo.lock
4 |
--------------------------------------------------------------------------------
/.rustfmt.toml:
--------------------------------------------------------------------------------
1 | use_small_heuristics = "Max"
2 | max_width = 120
3 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | resolver = "2"
3 |
4 | members = ["symbols", "symbols-models"]
5 |
6 | exclude = ["example"]
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Symbols
2 |
3 | ## What is this?
4 |
5 | 
6 |
7 | This is an utility to build a proc-macro that connects to a database, retrieves data from given table and populates an enum variants with primary keys values.
8 | It also generates a method for every non-primary-key field, and, when there are multiple primary keys, a costructor for every possible subset of primary keys.
9 |
10 | ## Replacements
11 |
12 | Replacements are done using annotated parameters.
13 | Basic replacements are written in the form `#[macro(field = "enum")]` or `#[macro(field(type = "enum"))]`, where we are telling to replace string values from `field` with variants from enum `enum`, variant names will be the CamelCase version of field value.
14 | Advanced replacements are done in the form `#[macro(field(type = "bar", fn = "foo"))]`, where we are telling to replace string values from `field` with a call to method `foo` from struct/enum `bar`, method output is expected to be of type `bar`.
15 | *WARNING:* Since all produced methods are `const`, also methods you pass this way must be `const`.
16 |
17 | ### Cache
18 |
19 | To avoid flooding the database with requests, light up macro run times and be able to work offline, data cache files are stored in temp folder under the name of `
.cache`.
20 | Quick way to delete it is to run
21 | ```bash
22 | find /tmp -name *.cache -delete
23 | ```
24 |
25 | ### Examples
26 |
27 | You can find a basic example in [example](./example) folder, it uses a mariadb container to load a database, you can run it with:
28 | ```bash
29 | docker-compose run rust
30 | ```
31 | Example code
32 | ```rust
33 | #[example::example(
34 | table = "best_selling_video_games",
35 | platforms(type = "Platforms", fn = "from_str"),
36 | developer = "Developer",
37 | publisher(type = "Publisher", fn = "from_str")
38 | )]
39 | pub enum BestSellingVideoGame {}
40 | ```
41 | would expand to
42 | ```rust
43 | pub enum BestSellingVideoGame {
44 | AnimalCrossingNewHorizons,
45 | Borderlands2,
46 | CallOfDutyBlackOps,
47 | CallOfDutyBlackOpsIi,
48 | CallOfDutyModernWarfare,
49 | CallOfDutyModernWarfare2,
50 | CallOfDutyModernWarfare3,
51 | DiabloIiiReaperOfSouls,
52 | DuckHunt,
53 | Fifa18,
54 | GrandTheftAutoIv,
55 | GrandTheftAutoV,
56 | GrandTheftAutoSanAndreas,
57 | HumanFallFlat,
58 | KinectAdventures,
59 | MarioKart8Deluxe,
60 | MarioKartDs,
61 | MarioKartWii,
62 | Minecraft,
63 | NewSuperMarioBros,
64 | NewSuperMarioBrosUDeluxeLuigiU,
65 | NewSuperMarioBrosWii,
66 | Nintendogs,
67 | PacMan,
68 | PokemonDiamondPearlPlatinum,
69 | PokemonGoldSilverCrystal,
70 | PokemonRedGreenBlueYellow,
71 | PokemonRubySapphireEmerald,
72 | PokemonSunMoonUltraSunUltraMoon,
73 | PokemonSwordShield,
74 | PubgBattlegrounds,
75 | RedDeadRedemption,
76 | RedDeadRedemption2,
77 | SonicTheHedgehog,
78 | SuperMario64Ds,
79 | SuperMarioBros,
80 | SuperMarioBros3,
81 | SuperMarioOdyssey,
82 | SuperMarioWorld,
83 | SuperSmashBrosUltimate,
84 | Terraria,
85 | TetrisEa,
86 | TetrisNintendo,
87 | TheElderScrollsVSkyrim,
88 | TheLegendOfZeldaBreathOfTheWild,
89 | TheWitcher3HeartsOfStoneBloodAndWine,
90 | WiiFitPlus,
91 | WiiPlay,
92 | WiiSports,
93 | WiiSportsResort,
94 | }
95 |
96 | impl BestSellingVideoGame {
97 | pub const fn initial_release_date(&self) -> &'static str {
98 | match self {
99 | BestSellingVideoGame::AnimalCrossingNewHorizons => "March 20, 2020",
100 | BestSellingVideoGame::Borderlands2 => "September 18, 2012",
101 | BestSellingVideoGame::CallOfDutyBlackOps => "November 9, 2010",
102 | BestSellingVideoGame::CallOfDutyBlackOpsIi => "November 12, 2012",
103 | BestSellingVideoGame::CallOfDutyModernWarfare => "October 25, 2019",
104 | BestSellingVideoGame::CallOfDutyModernWarfare2 => "November 10, 2009",
105 | BestSellingVideoGame::CallOfDutyModernWarfare3 => "November 8, 2011",
106 | BestSellingVideoGame::DiabloIiiReaperOfSouls => "May 16, 2012",
107 | BestSellingVideoGame::DuckHunt => "April 21, 1984",
108 | BestSellingVideoGame::Fifa18 => "September 29, 2017",
109 | BestSellingVideoGame::GrandTheftAutoIv => "April 29, 2008",
110 | BestSellingVideoGame::GrandTheftAutoV => "September 17, 2013",
111 | BestSellingVideoGame::GrandTheftAutoSanAndreas => "October 26, 2004",
112 | BestSellingVideoGame::HumanFallFlat => "July 22, 2016",
113 | BestSellingVideoGame::KinectAdventures => "November 4, 2010",
114 | BestSellingVideoGame::MarioKart8Deluxe => "May 29, 2014",
115 | BestSellingVideoGame::MarioKartDs => "November 14, 2005",
116 | BestSellingVideoGame::MarioKartWii => "April 10, 2008",
117 | BestSellingVideoGame::Minecraft => "November 18, 2011",
118 | BestSellingVideoGame::NewSuperMarioBros => "May 15, 2006",
119 | BestSellingVideoGame::NewSuperMarioBrosUDeluxeLuigiU => "November 18, 2012",
120 | BestSellingVideoGame::NewSuperMarioBrosWii => "November 11, 2009",
121 | BestSellingVideoGame::Nintendogs => "April 21, 2005",
122 | BestSellingVideoGame::PacMan => "May 22, 1980",
123 | BestSellingVideoGame::PokemonDiamondPearlPlatinum => "September 28, 2006",
124 | BestSellingVideoGame::PokemonGoldSilverCrystal => "November 21, 1999",
125 | BestSellingVideoGame::PokemonRedGreenBlueYellow => "February 27, 1996",
126 | BestSellingVideoGame::PokemonRubySapphireEmerald => "November 21, 2002",
127 | BestSellingVideoGame::PokemonSunMoonUltraSunUltraMoon => "November 18, 2016",
128 | BestSellingVideoGame::PokemonSwordShield => "November 15, 2019",
129 | BestSellingVideoGame::PubgBattlegrounds => "December 20, 2017",
130 | BestSellingVideoGame::RedDeadRedemption => "May 18, 2010",
131 | BestSellingVideoGame::RedDeadRedemption2 => "October 26, 2018",
132 | BestSellingVideoGame::SonicTheHedgehog => "June 23, 1991",
133 | BestSellingVideoGame::SuperMario64Ds => "June 23, 1996",
134 | BestSellingVideoGame::SuperMarioBros => "September 13, 1985",
135 | BestSellingVideoGame::SuperMarioBros3 => "October 23, 1988",
136 | BestSellingVideoGame::SuperMarioOdyssey => "October 27, 2017",
137 | BestSellingVideoGame::SuperMarioWorld => "November 21, 1990",
138 | BestSellingVideoGame::SuperSmashBrosUltimate => "December 7, 2018",
139 | BestSellingVideoGame::Terraria => "May 16, 2011",
140 | BestSellingVideoGame::TetrisEa => "September 12, 2006",
141 | BestSellingVideoGame::TetrisNintendo => "June 14, 1989",
142 | BestSellingVideoGame::TheElderScrollsVSkyrim => "November 11, 2011",
143 | BestSellingVideoGame::TheLegendOfZeldaBreathOfTheWild => "March 3, 2017",
144 | BestSellingVideoGame::TheWitcher3HeartsOfStoneBloodAndWine => "May 19, 2015",
145 | BestSellingVideoGame::WiiFitPlus => "December 1, 2007",
146 | BestSellingVideoGame::WiiPlay => "December 2, 2006",
147 | BestSellingVideoGame::WiiSports => "November 19, 2006",
148 | BestSellingVideoGame::WiiSportsResort => "June 25, 2009",
149 | }
150 | }
151 | pub const fn rank(&self) -> i8 {
152 | match self {
153 | BestSellingVideoGame::AnimalCrossingNewHorizons => 15,
154 | BestSellingVideoGame::Borderlands2 => 33,
155 | BestSellingVideoGame::CallOfDutyBlackOps => 32,
156 | BestSellingVideoGame::CallOfDutyBlackOpsIi => 38,
157 | BestSellingVideoGame::CallOfDutyModernWarfare => 20,
158 | BestSellingVideoGame::CallOfDutyModernWarfare2 => 48,
159 | BestSellingVideoGame::CallOfDutyModernWarfare3 => 31,
160 | BestSellingVideoGame::DiabloIiiReaperOfSouls => 20,
161 | BestSellingVideoGame::DuckHunt => 25,
162 | BestSellingVideoGame::Fifa18 => 39,
163 | BestSellingVideoGame::GrandTheftAutoIv => 35,
164 | BestSellingVideoGame::GrandTheftAutoV => 2,
165 | BestSellingVideoGame::GrandTheftAutoSanAndreas => 27,
166 | BestSellingVideoGame::HumanFallFlat => 20,
167 | BestSellingVideoGame::KinectAdventures => 39,
168 | BestSellingVideoGame::MarioKart8Deluxe => 7,
169 | BestSellingVideoGame::MarioKartDs => 44,
170 | BestSellingVideoGame::MarioKartWii => 16,
171 | BestSellingVideoGame::Minecraft => 1,
172 | BestSellingVideoGame::NewSuperMarioBros => 18,
173 | BestSellingVideoGame::NewSuperMarioBrosUDeluxeLuigiU => 50,
174 | BestSellingVideoGame::NewSuperMarioBrosWii => 19,
175 | BestSellingVideoGame::Nintendogs => 42,
176 | BestSellingVideoGame::PacMan => 13,
177 | BestSellingVideoGame::PokemonDiamondPearlPlatinum => 36,
178 | BestSellingVideoGame::PokemonGoldSilverCrystal => 24,
179 | BestSellingVideoGame::PokemonRedGreenBlueYellow => 8,
180 | BestSellingVideoGame::PokemonRubySapphireEmerald => 49,
181 | BestSellingVideoGame::PokemonSunMoonUltraSunUltraMoon => 34,
182 | BestSellingVideoGame::PokemonSwordShield => 43,
183 | BestSellingVideoGame::PubgBattlegrounds => 5,
184 | BestSellingVideoGame::RedDeadRedemption => 46,
185 | BestSellingVideoGame::RedDeadRedemption2 => 11,
186 | BestSellingVideoGame::SonicTheHedgehog => 41,
187 | BestSellingVideoGame::SuperMario64Ds => 47,
188 | BestSellingVideoGame::SuperMarioBros => 6,
189 | BestSellingVideoGame::SuperMarioBros3 => 37,
190 | BestSellingVideoGame::SuperMarioOdyssey => 45,
191 | BestSellingVideoGame::SuperMarioWorld => 30,
192 | BestSellingVideoGame::SuperSmashBrosUltimate => 29,
193 | BestSellingVideoGame::Terraria => 9,
194 | BestSellingVideoGame::TetrisEa => 3,
195 | BestSellingVideoGame::TetrisNintendo => 11,
196 | BestSellingVideoGame::TheElderScrollsVSkyrim => 20,
197 | BestSellingVideoGame::TheLegendOfZeldaBreathOfTheWild => 28,
198 | BestSellingVideoGame::TheWitcher3HeartsOfStoneBloodAndWine => 14,
199 | BestSellingVideoGame::WiiFitPlus => 10,
200 | BestSellingVideoGame::WiiPlay => 26,
201 | BestSellingVideoGame::WiiSports => 4,
202 | BestSellingVideoGame::WiiSportsResort => 17,
203 | }
204 | }
205 | pub const fn sales(&self) -> &'static str {
206 | match self {
207 | BestSellingVideoGame::AnimalCrossingNewHorizons => "37,620,000",
208 | BestSellingVideoGame::Borderlands2 => "26,000,000",
209 | BestSellingVideoGame::CallOfDutyBlackOps => "26,200,000",
210 | BestSellingVideoGame::CallOfDutyBlackOpsIi => "24,200,000",
211 | BestSellingVideoGame::CallOfDutyModernWarfare => "30,000,000",
212 | BestSellingVideoGame::CallOfDutyModernWarfare2 => "22,700,000",
213 | BestSellingVideoGame::CallOfDutyModernWarfare3 => "26,500,000",
214 | BestSellingVideoGame::DiabloIiiReaperOfSouls => "30,000,000",
215 | BestSellingVideoGame::DuckHunt => "28,300,000",
216 | BestSellingVideoGame::Fifa18 => "24,000,000",
217 | BestSellingVideoGame::GrandTheftAutoIv => "25,000,000",
218 | BestSellingVideoGame::GrandTheftAutoV => "160,000,000",
219 | BestSellingVideoGame::GrandTheftAutoSanAndreas => "27,500,000",
220 | BestSellingVideoGame::HumanFallFlat => "30,000,000",
221 | BestSellingVideoGame::KinectAdventures => "24,000,000",
222 | BestSellingVideoGame::MarioKart8Deluxe => "51,810,000",
223 | BestSellingVideoGame::MarioKartDs => "23,600,000",
224 | BestSellingVideoGame::MarioKartWii => "37,380,000",
225 | BestSellingVideoGame::Minecraft => "238,000,000",
226 | BestSellingVideoGame::NewSuperMarioBros => "30,800,000",
227 | BestSellingVideoGame::NewSuperMarioBrosUDeluxeLuigiU => "21,600,000",
228 | BestSellingVideoGame::NewSuperMarioBrosWii => "30,320,000",
229 | BestSellingVideoGame::Nintendogs => "23,960,000",
230 | BestSellingVideoGame::PacMan => "42,071,635",
231 | BestSellingVideoGame::PokemonDiamondPearlPlatinum => "24,730,000",
232 | BestSellingVideoGame::PokemonGoldSilverCrystal => "29,490,000",
233 | BestSellingVideoGame::PokemonRedGreenBlueYellow => "47,520,000",
234 | BestSellingVideoGame::PokemonRubySapphireEmerald => "22,540,000",
235 | BestSellingVideoGame::PokemonSunMoonUltraSunUltraMoon => "25,310,000",
236 | BestSellingVideoGame::PokemonSwordShield => "23,900,000",
237 | BestSellingVideoGame::PubgBattlegrounds => "75,000,000",
238 | BestSellingVideoGame::RedDeadRedemption => "23,000,000",
239 | BestSellingVideoGame::RedDeadRedemption2 => "43,000,000",
240 | BestSellingVideoGame::SonicTheHedgehog => "23,982,960",
241 | BestSellingVideoGame::SuperMario64Ds => "22,960,000",
242 | BestSellingVideoGame::SuperMarioBros => "58,000,000",
243 | BestSellingVideoGame::SuperMarioBros3 => "24,430,000",
244 | BestSellingVideoGame::SuperMarioOdyssey => "23,020,000",
245 | BestSellingVideoGame::SuperMarioWorld => "26,662,500",
246 | BestSellingVideoGame::SuperSmashBrosUltimate => "27,400,000",
247 | BestSellingVideoGame::Terraria => "44,000,000",
248 | BestSellingVideoGame::TetrisEa => "100,000,000",
249 | BestSellingVideoGame::TetrisNintendo => "43,000,000",
250 | BestSellingVideoGame::TheElderScrollsVSkyrim => "30,000,000",
251 | BestSellingVideoGame::TheLegendOfZeldaBreathOfTheWild => "27,490,000",
252 | BestSellingVideoGame::TheWitcher3HeartsOfStoneBloodAndWine => "40,000,000",
253 | BestSellingVideoGame::WiiFitPlus => "43,800,000",
254 | BestSellingVideoGame::WiiPlay => "28,020,000",
255 | BestSellingVideoGame::WiiSports => "82,900,000",
256 | BestSellingVideoGame::WiiSportsResort => "33,140,000",
257 | }
258 | }
259 | pub const fn as_str(&self) -> &'static str {
260 | match self {
261 | BestSellingVideoGame::AnimalCrossingNewHorizons => "Animal Crossing: New Horizons",
262 | BestSellingVideoGame::Borderlands2 => "Borderlands 2",
263 | BestSellingVideoGame::CallOfDutyBlackOps => "Call of Duty: Black Ops",
264 | BestSellingVideoGame::CallOfDutyBlackOpsIi => "Call of Duty: Black Ops II",
265 | BestSellingVideoGame::CallOfDutyModernWarfare => "Call of Duty: Modern Warfare",
266 | BestSellingVideoGame::CallOfDutyModernWarfare2 => "Call of Duty: Modern Warfare 2",
267 | BestSellingVideoGame::CallOfDutyModernWarfare3 => "Call of Duty: Modern Warfare 3",
268 | BestSellingVideoGame::DiabloIiiReaperOfSouls => "Diablo III / Reaper of Souls",
269 | BestSellingVideoGame::DuckHunt => "Duck Hunt",
270 | BestSellingVideoGame::Fifa18 => "FIFA 18",
271 | BestSellingVideoGame::GrandTheftAutoIv => "Grand Theft Auto IV",
272 | BestSellingVideoGame::GrandTheftAutoV => "Grand Theft Auto V",
273 | BestSellingVideoGame::GrandTheftAutoSanAndreas => "Grand Theft Auto: San Andreas",
274 | BestSellingVideoGame::HumanFallFlat => "Human: Fall Flat",
275 | BestSellingVideoGame::KinectAdventures => "Kinect Adventures!",
276 | BestSellingVideoGame::MarioKart8Deluxe => "Mario Kart 8 / Deluxe",
277 | BestSellingVideoGame::MarioKartDs => "Mario Kart DS",
278 | BestSellingVideoGame::MarioKartWii => "Mario Kart Wii",
279 | BestSellingVideoGame::Minecraft => "Minecraft",
280 | BestSellingVideoGame::NewSuperMarioBros => "New Super Mario Bros.",
281 | BestSellingVideoGame::NewSuperMarioBrosUDeluxeLuigiU => {
282 | "New Super Mario Bros. U / Deluxe / Luigi U"
283 | }
284 | BestSellingVideoGame::NewSuperMarioBrosWii => "New Super Mario Bros. Wii",
285 | BestSellingVideoGame::Nintendogs => "Nintendogs",
286 | BestSellingVideoGame::PacMan => "Pac-Man",
287 | BestSellingVideoGame::PokemonDiamondPearlPlatinum => {
288 | "Pokemon Diamond / Pearl / Platinum"
289 | }
290 | BestSellingVideoGame::PokemonGoldSilverCrystal => "Pokemon Gold / Silver / Crystal",
291 | BestSellingVideoGame::PokemonRedGreenBlueYellow => {
292 | "Pokemon Red / Green / Blue / Yellow"
293 | }
294 | BestSellingVideoGame::PokemonRubySapphireEmerald => "Pokemon Ruby / Sapphire / Emerald",
295 | BestSellingVideoGame::PokemonSunMoonUltraSunUltraMoon => {
296 | "Pokemon Sun / Moon / Ultra Sun / Ultra Moon"
297 | }
298 | BestSellingVideoGame::PokemonSwordShield => "Pokemon Sword / Shield",
299 | BestSellingVideoGame::PubgBattlegrounds => "PUBG: Battlegrounds",
300 | BestSellingVideoGame::RedDeadRedemption => "Red Dead Redemption",
301 | BestSellingVideoGame::RedDeadRedemption2 => "Red Dead Redemption 2",
302 | BestSellingVideoGame::SonicTheHedgehog => "Sonic the Hedgehog",
303 | BestSellingVideoGame::SuperMario64Ds => "Super Mario 64 / DS",
304 | BestSellingVideoGame::SuperMarioBros => "Super Mario Bros.",
305 | BestSellingVideoGame::SuperMarioBros3 => "Super Mario Bros. 3",
306 | BestSellingVideoGame::SuperMarioOdyssey => "Super Mario Odyssey",
307 | BestSellingVideoGame::SuperMarioWorld => "Super Mario World",
308 | BestSellingVideoGame::SuperSmashBrosUltimate => "Super Smash Bros. Ultimate",
309 | BestSellingVideoGame::Terraria => "Terraria",
310 | BestSellingVideoGame::TetrisEa => "Tetris (EA)",
311 | BestSellingVideoGame::TetrisNintendo => "Tetris (Nintendo)",
312 | BestSellingVideoGame::TheElderScrollsVSkyrim => "The Elder Scrolls V: Skyrim",
313 | BestSellingVideoGame::TheLegendOfZeldaBreathOfTheWild => {
314 | "The Legend of Zelda: Breath of the Wild"
315 | }
316 | BestSellingVideoGame::TheWitcher3HeartsOfStoneBloodAndWine => {
317 | "The Witcher 3 / Hearts of Stone / Blood and Wine"
318 | }
319 | BestSellingVideoGame::WiiFitPlus => "Wii Fit / Plus",
320 | BestSellingVideoGame::WiiPlay => "Wii Play",
321 | BestSellingVideoGame::WiiSports => "Wii Sports",
322 | BestSellingVideoGame::WiiSportsResort => "Wii Sports Resort",
323 | }
324 | }
325 | pub const fn series(&self) -> &'static str {
326 | match self {
327 | BestSellingVideoGame::AnimalCrossingNewHorizons => "Animal Crossing",
328 | BestSellingVideoGame::Borderlands2 => "Borderlands",
329 | BestSellingVideoGame::CallOfDutyBlackOps => "Call of Duty",
330 | BestSellingVideoGame::CallOfDutyBlackOpsIi => "Call of Duty",
331 | BestSellingVideoGame::CallOfDutyModernWarfare => "Call of Duty",
332 | BestSellingVideoGame::CallOfDutyModernWarfare2 => "Call of Duty",
333 | BestSellingVideoGame::CallOfDutyModernWarfare3 => "Call of Duty",
334 | BestSellingVideoGame::DiabloIiiReaperOfSouls => "Diablo",
335 | BestSellingVideoGame::DuckHunt => "None",
336 | BestSellingVideoGame::Fifa18 => "FIFA",
337 | BestSellingVideoGame::GrandTheftAutoIv => "Grand Theft Auto",
338 | BestSellingVideoGame::GrandTheftAutoV => "Grand Theft Auto",
339 | BestSellingVideoGame::GrandTheftAutoSanAndreas => "Grand Theft Auto",
340 | BestSellingVideoGame::HumanFallFlat => "None",
341 | BestSellingVideoGame::KinectAdventures => "None",
342 | BestSellingVideoGame::MarioKart8Deluxe => "Mario Kart",
343 | BestSellingVideoGame::MarioKartDs => "Mario Kart",
344 | BestSellingVideoGame::MarioKartWii => "Mario Kart",
345 | BestSellingVideoGame::Minecraft => "Minecraft",
346 | BestSellingVideoGame::NewSuperMarioBros => "Super Mario",
347 | BestSellingVideoGame::NewSuperMarioBrosUDeluxeLuigiU => "Super Mario",
348 | BestSellingVideoGame::NewSuperMarioBrosWii => "Super Mario",
349 | BestSellingVideoGame::Nintendogs => "None",
350 | BestSellingVideoGame::PacMan => "Pac-Man",
351 | BestSellingVideoGame::PokemonDiamondPearlPlatinum => "Pokemon",
352 | BestSellingVideoGame::PokemonGoldSilverCrystal => "Pokemon",
353 | BestSellingVideoGame::PokemonRedGreenBlueYellow => "Pokemon",
354 | BestSellingVideoGame::PokemonRubySapphireEmerald => "Pokemon",
355 | BestSellingVideoGame::PokemonSunMoonUltraSunUltraMoon => "Pokemon",
356 | BestSellingVideoGame::PokemonSwordShield => "Pokemon",
357 | BestSellingVideoGame::PubgBattlegrounds => "PUBG Universe",
358 | BestSellingVideoGame::RedDeadRedemption => "Red Dead",
359 | BestSellingVideoGame::RedDeadRedemption2 => "Red Dead",
360 | BestSellingVideoGame::SonicTheHedgehog => "Sonic the Hedgehog",
361 | BestSellingVideoGame::SuperMario64Ds => "Super Mario",
362 | BestSellingVideoGame::SuperMarioBros => "Super Mario",
363 | BestSellingVideoGame::SuperMarioBros3 => "Super Mario",
364 | BestSellingVideoGame::SuperMarioOdyssey => "Super Mario",
365 | BestSellingVideoGame::SuperMarioWorld => "Super Mario",
366 | BestSellingVideoGame::SuperSmashBrosUltimate => "Super Smash Bros.",
367 | BestSellingVideoGame::Terraria => "None",
368 | BestSellingVideoGame::TetrisEa => "Tetris",
369 | BestSellingVideoGame::TetrisNintendo => "Tetris",
370 | BestSellingVideoGame::TheElderScrollsVSkyrim => "The Elder Scrolls",
371 | BestSellingVideoGame::TheLegendOfZeldaBreathOfTheWild => "The Legend of Zelda",
372 | BestSellingVideoGame::TheWitcher3HeartsOfStoneBloodAndWine => "The Witcher",
373 | BestSellingVideoGame::WiiFitPlus => "Wii",
374 | BestSellingVideoGame::WiiPlay => "Wii",
375 | BestSellingVideoGame::WiiSports => "Wii",
376 | BestSellingVideoGame::WiiSportsResort => "Wii",
377 | }
378 | }
379 | pub const fn platforms(&self) -> Platforms {
380 | match self {
381 | BestSellingVideoGame::AnimalCrossingNewHorizons => {
382 | Platforms::from_str("Nintendo Switch")
383 | }
384 | BestSellingVideoGame::Borderlands2 => Platforms::from_str("Multi-platform"),
385 | BestSellingVideoGame::CallOfDutyBlackOps => Platforms::from_str("Multi-platform"),
386 | BestSellingVideoGame::CallOfDutyBlackOpsIi => Platforms::from_str("Multi-platform"),
387 | BestSellingVideoGame::CallOfDutyModernWarfare => Platforms::from_str("Multi-platform"),
388 | BestSellingVideoGame::CallOfDutyModernWarfare2 => Platforms::from_str("Multi-platform"),
389 | BestSellingVideoGame::CallOfDutyModernWarfare3 => Platforms::from_str("Multi-platform"),
390 | BestSellingVideoGame::DiabloIiiReaperOfSouls => Platforms::from_str("Multi-platform"),
391 | BestSellingVideoGame::DuckHunt => Platforms::from_str("NES"),
392 | BestSellingVideoGame::Fifa18 => Platforms::from_str("Multi-platform"),
393 | BestSellingVideoGame::GrandTheftAutoIv => Platforms::from_str("Multi-platform"),
394 | BestSellingVideoGame::GrandTheftAutoV => Platforms::from_str("Multi-platform"),
395 | BestSellingVideoGame::GrandTheftAutoSanAndreas => Platforms::from_str("Multi-platform"),
396 | BestSellingVideoGame::HumanFallFlat => Platforms::from_str("Multi-platform"),
397 | BestSellingVideoGame::KinectAdventures => Platforms::from_str("Xbox 360"),
398 | BestSellingVideoGame::MarioKart8Deluxe => Platforms::from_str("Wii U / Switch"),
399 | BestSellingVideoGame::MarioKartDs => Platforms::from_str("Nintendo DS"),
400 | BestSellingVideoGame::MarioKartWii => Platforms::from_str("Wii"),
401 | BestSellingVideoGame::Minecraft => Platforms::from_str("Multi-platform"),
402 | BestSellingVideoGame::NewSuperMarioBros => Platforms::from_str("Nintendo DS"),
403 | BestSellingVideoGame::NewSuperMarioBrosUDeluxeLuigiU => {
404 | Platforms::from_str("Wii U / Nintendo Switch")
405 | }
406 | BestSellingVideoGame::NewSuperMarioBrosWii => Platforms::from_str("Wii"),
407 | BestSellingVideoGame::Nintendogs => Platforms::from_str("Nintendo DS"),
408 | BestSellingVideoGame::PacMan => Platforms::from_str("Multi-platform"),
409 | BestSellingVideoGame::PokemonDiamondPearlPlatinum => Platforms::from_str("Nintendo DS"),
410 | BestSellingVideoGame::PokemonGoldSilverCrystal => Platforms::from_str("Game Boy Color"),
411 | BestSellingVideoGame::PokemonRedGreenBlueYellow => {
412 | Platforms::from_str("Game Boy / Color")
413 | }
414 | BestSellingVideoGame::PokemonRubySapphireEmerald => {
415 | Platforms::from_str("Game Boy Advance")
416 | }
417 | BestSellingVideoGame::PokemonSunMoonUltraSunUltraMoon => {
418 | Platforms::from_str("Nintendo 3DS")
419 | }
420 | BestSellingVideoGame::PokemonSwordShield => Platforms::from_str("Nintendo Switch"),
421 | BestSellingVideoGame::PubgBattlegrounds => Platforms::from_str("Multi-platform"),
422 | BestSellingVideoGame::RedDeadRedemption => Platforms::from_str("PS3 / Xbox 360"),
423 | BestSellingVideoGame::RedDeadRedemption2 => Platforms::from_str("Multi-platform"),
424 | BestSellingVideoGame::SonicTheHedgehog => Platforms::from_str("Multi-platform"),
425 | BestSellingVideoGame::SuperMario64Ds => Platforms::from_str("Nintendo 64 / DS"),
426 | BestSellingVideoGame::SuperMarioBros => Platforms::from_str("Multi-platform"),
427 | BestSellingVideoGame::SuperMarioBros3 => Platforms::from_str("Multi-platform"),
428 | BestSellingVideoGame::SuperMarioOdyssey => Platforms::from_str("Nintendo Switch"),
429 | BestSellingVideoGame::SuperMarioWorld => Platforms::from_str("Multi-platform"),
430 | BestSellingVideoGame::SuperSmashBrosUltimate => Platforms::from_str("Nintendo Switch"),
431 | BestSellingVideoGame::Terraria => Platforms::from_str("Multi-platform"),
432 | BestSellingVideoGame::TetrisEa => Platforms::from_str("Multi-platform"),
433 | BestSellingVideoGame::TetrisNintendo => Platforms::from_str("Game Boy / NES"),
434 | BestSellingVideoGame::TheElderScrollsVSkyrim => Platforms::from_str("Multi-platform"),
435 | BestSellingVideoGame::TheLegendOfZeldaBreathOfTheWild => {
436 | Platforms::from_str("Wii U / Switch")
437 | }
438 | BestSellingVideoGame::TheWitcher3HeartsOfStoneBloodAndWine => {
439 | Platforms::from_str("Multi-platform")
440 | }
441 | BestSellingVideoGame::WiiFitPlus => Platforms::from_str("Wii"),
442 | BestSellingVideoGame::WiiPlay => Platforms::from_str("Wii"),
443 | BestSellingVideoGame::WiiSports => Platforms::from_str("Wii"),
444 | BestSellingVideoGame::WiiSportsResort => Platforms::from_str("Wii"),
445 | }
446 | }
447 | pub const fn publisher(&self) -> Publisher {
448 | match self {
449 | BestSellingVideoGame::AnimalCrossingNewHorizons => Publisher::from_str("Nintendo"),
450 | BestSellingVideoGame::Borderlands2 => Publisher::from_str("2K Games"),
451 | BestSellingVideoGame::CallOfDutyBlackOps => Publisher::from_str("Activision"),
452 | BestSellingVideoGame::CallOfDutyBlackOpsIi => Publisher::from_str("Activision"),
453 | BestSellingVideoGame::CallOfDutyModernWarfare => Publisher::from_str("Activision"),
454 | BestSellingVideoGame::CallOfDutyModernWarfare2 => Publisher::from_str("Activision"),
455 | BestSellingVideoGame::CallOfDutyModernWarfare3 => Publisher::from_str("Activision"),
456 | BestSellingVideoGame::DiabloIiiReaperOfSouls => {
457 | Publisher::from_str("Blizzard Entertainment")
458 | }
459 | BestSellingVideoGame::DuckHunt => Publisher::from_str("Nintendo"),
460 | BestSellingVideoGame::Fifa18 => Publisher::from_str("EA Sports"),
461 | BestSellingVideoGame::GrandTheftAutoIv => Publisher::from_str("Rockstar Games"),
462 | BestSellingVideoGame::GrandTheftAutoV => Publisher::from_str("Rockstar Games"),
463 | BestSellingVideoGame::GrandTheftAutoSanAndreas => Publisher::from_str("Rockstar Games"),
464 | BestSellingVideoGame::HumanFallFlat => Publisher::from_str("Curve Digital"),
465 | BestSellingVideoGame::KinectAdventures => Publisher::from_str("Xbox Game Studios"),
466 | BestSellingVideoGame::MarioKart8Deluxe => Publisher::from_str("Nintendo"),
467 | BestSellingVideoGame::MarioKartDs => Publisher::from_str("Nintendo"),
468 | BestSellingVideoGame::MarioKartWii => Publisher::from_str("Nintendo"),
469 | BestSellingVideoGame::Minecraft => Publisher::from_str("Xbox Game Studios"),
470 | BestSellingVideoGame::NewSuperMarioBros => Publisher::from_str("Nintendo"),
471 | BestSellingVideoGame::NewSuperMarioBrosUDeluxeLuigiU => Publisher::from_str("Nintendo"),
472 | BestSellingVideoGame::NewSuperMarioBrosWii => Publisher::from_str("Nintendo"),
473 | BestSellingVideoGame::Nintendogs => Publisher::from_str("Nintendo"),
474 | BestSellingVideoGame::PacMan => Publisher::from_str("Namco"),
475 | BestSellingVideoGame::PokemonDiamondPearlPlatinum => {
476 | Publisher::from_str("Nintendo / The Pokemon Company")
477 | }
478 | BestSellingVideoGame::PokemonGoldSilverCrystal => Publisher::from_str("Nintendo"),
479 | BestSellingVideoGame::PokemonRedGreenBlueYellow => Publisher::from_str("Nintendo"),
480 | BestSellingVideoGame::PokemonRubySapphireEmerald => {
481 | Publisher::from_str("Nintendo / The Pokemon Company")
482 | }
483 | BestSellingVideoGame::PokemonSunMoonUltraSunUltraMoon => {
484 | Publisher::from_str("Nintendo / The Pokemon Company")
485 | }
486 | BestSellingVideoGame::PokemonSwordShield => {
487 | Publisher::from_str("Nintendo / The Pokemon Company")
488 | }
489 | BestSellingVideoGame::PubgBattlegrounds => Publisher::from_str("PUBG Corporation"),
490 | BestSellingVideoGame::RedDeadRedemption => Publisher::from_str("Rockstar Games"),
491 | BestSellingVideoGame::RedDeadRedemption2 => Publisher::from_str("Rockstar Games"),
492 | BestSellingVideoGame::SonicTheHedgehog => Publisher::from_str("Sega"),
493 | BestSellingVideoGame::SuperMario64Ds => Publisher::from_str("Nintendo"),
494 | BestSellingVideoGame::SuperMarioBros => Publisher::from_str("Nintendo"),
495 | BestSellingVideoGame::SuperMarioBros3 => Publisher::from_str("Nintendo"),
496 | BestSellingVideoGame::SuperMarioOdyssey => Publisher::from_str("Nintendo"),
497 | BestSellingVideoGame::SuperMarioWorld => Publisher::from_str("Nintendo"),
498 | BestSellingVideoGame::SuperSmashBrosUltimate => Publisher::from_str("Nintendo"),
499 | BestSellingVideoGame::Terraria => Publisher::from_str("Re-Logic / 505 Games"),
500 | BestSellingVideoGame::TetrisEa => Publisher::from_str("Electronic Arts"),
501 | BestSellingVideoGame::TetrisNintendo => Publisher::from_str("Nintendo"),
502 | BestSellingVideoGame::TheElderScrollsVSkyrim => {
503 | Publisher::from_str("Bethesda Softworks")
504 | }
505 | BestSellingVideoGame::TheLegendOfZeldaBreathOfTheWild => {
506 | Publisher::from_str("Nintendo")
507 | }
508 | BestSellingVideoGame::TheWitcher3HeartsOfStoneBloodAndWine => {
509 | Publisher::from_str("CD Projekt")
510 | }
511 | BestSellingVideoGame::WiiFitPlus => Publisher::from_str("Nintendo"),
512 | BestSellingVideoGame::WiiPlay => Publisher::from_str("Nintendo"),
513 | BestSellingVideoGame::WiiSports => Publisher::from_str("Nintendo"),
514 | BestSellingVideoGame::WiiSportsResort => Publisher::from_str("Nintendo"),
515 | }
516 | }
517 | pub const fn developer(&self) -> Developer {
518 | match self {
519 | BestSellingVideoGame::AnimalCrossingNewHorizons => Developer::NintendoEpd,
520 | BestSellingVideoGame::Borderlands2 => Developer::GearboxSoftware,
521 | BestSellingVideoGame::CallOfDutyBlackOps => Developer::Treyarch,
522 | BestSellingVideoGame::CallOfDutyBlackOpsIi => Developer::Treyarch,
523 | BestSellingVideoGame::CallOfDutyModernWarfare => Developer::InfinityWard,
524 | BestSellingVideoGame::CallOfDutyModernWarfare2 => Developer::InfinityWard,
525 | BestSellingVideoGame::CallOfDutyModernWarfare3 => Developer::InfinityWardSledgehammer,
526 | BestSellingVideoGame::DiabloIiiReaperOfSouls => Developer::BlizzardEntertainment,
527 | BestSellingVideoGame::DuckHunt => Developer::NintendoRD1,
528 | BestSellingVideoGame::Fifa18 => Developer::EaVancouver,
529 | BestSellingVideoGame::GrandTheftAutoIv => Developer::RockstarNorth,
530 | BestSellingVideoGame::GrandTheftAutoV => Developer::RockstarNorth,
531 | BestSellingVideoGame::GrandTheftAutoSanAndreas => Developer::RockstarNorth,
532 | BestSellingVideoGame::HumanFallFlat => Developer::NoBrakesGames,
533 | BestSellingVideoGame::KinectAdventures => Developer::GoodScienceStudio,
534 | BestSellingVideoGame::MarioKart8Deluxe => Developer::NintendoEad,
535 | BestSellingVideoGame::MarioKartDs => Developer::NintendoEad,
536 | BestSellingVideoGame::MarioKartWii => Developer::NintendoEad,
537 | BestSellingVideoGame::Minecraft => Developer::MojangStudios,
538 | BestSellingVideoGame::NewSuperMarioBros => Developer::NintendoEad,
539 | BestSellingVideoGame::NewSuperMarioBrosUDeluxeLuigiU => Developer::NintendoEad,
540 | BestSellingVideoGame::NewSuperMarioBrosWii => Developer::NintendoEad,
541 | BestSellingVideoGame::Nintendogs => Developer::NintendoEad,
542 | BestSellingVideoGame::PacMan => Developer::Namco,
543 | BestSellingVideoGame::PokemonDiamondPearlPlatinum => Developer::GameFreak,
544 | BestSellingVideoGame::PokemonGoldSilverCrystal => Developer::GameFreak,
545 | BestSellingVideoGame::PokemonRedGreenBlueYellow => Developer::GameFreak,
546 | BestSellingVideoGame::PokemonRubySapphireEmerald => Developer::GameFreak,
547 | BestSellingVideoGame::PokemonSunMoonUltraSunUltraMoon => Developer::GameFreak,
548 | BestSellingVideoGame::PokemonSwordShield => Developer::GameFreak,
549 | BestSellingVideoGame::PubgBattlegrounds => Developer::PubgCorporation,
550 | BestSellingVideoGame::RedDeadRedemption => Developer::RockstarSanDiego,
551 | BestSellingVideoGame::RedDeadRedemption2 => Developer::RockstarStudios,
552 | BestSellingVideoGame::SonicTheHedgehog => Developer::SonicTeam,
553 | BestSellingVideoGame::SuperMario64Ds => Developer::NintendoEad,
554 | BestSellingVideoGame::SuperMarioBros => Developer::NintendoRD4,
555 | BestSellingVideoGame::SuperMarioBros3 => Developer::NintendoEad,
556 | BestSellingVideoGame::SuperMarioOdyssey => Developer::NintendoEpd,
557 | BestSellingVideoGame::SuperMarioWorld => Developer::NintendoEad,
558 | BestSellingVideoGame::SuperSmashBrosUltimate => Developer::BandaiNamcoStudiosSoraLtd,
559 | BestSellingVideoGame::Terraria => Developer::ReLogic,
560 | BestSellingVideoGame::TetrisEa => Developer::EaMobile,
561 | BestSellingVideoGame::TetrisNintendo => Developer::NintendoRD1,
562 | BestSellingVideoGame::TheElderScrollsVSkyrim => Developer::BethesdaGameStudios,
563 | BestSellingVideoGame::TheLegendOfZeldaBreathOfTheWild => Developer::NintendoEpd,
564 | BestSellingVideoGame::TheWitcher3HeartsOfStoneBloodAndWine => Developer::CdProjektRed,
565 | BestSellingVideoGame::WiiFitPlus => Developer::NintendoEad,
566 | BestSellingVideoGame::WiiPlay => Developer::NintendoEad,
567 | BestSellingVideoGame::WiiSports => Developer::NintendoEad,
568 | BestSellingVideoGame::WiiSportsResort => Developer::NintendoEad,
569 | }
570 | }
571 | }
572 |
573 | impl<'a> TryFrom<&'a str> for BestSellingVideoGame {
574 | type Error = String;
575 | fn try_from(s: &'a str) -> Result {
576 | match s {
577 | "Animal Crossing: New Horizons" => Ok(BestSellingVideoGame::AnimalCrossingNewHorizons),
578 | "Borderlands 2" => Ok(BestSellingVideoGame::Borderlands2),
579 | "Call of Duty: Black Ops" => Ok(BestSellingVideoGame::CallOfDutyBlackOps),
580 | "Call of Duty: Black Ops II" => Ok(BestSellingVideoGame::CallOfDutyBlackOpsIi),
581 | "Call of Duty: Modern Warfare" => Ok(BestSellingVideoGame::CallOfDutyModernWarfare),
582 | "Call of Duty: Modern Warfare 2" => Ok(BestSellingVideoGame::CallOfDutyModernWarfare2),
583 | "Call of Duty: Modern Warfare 3" => Ok(BestSellingVideoGame::CallOfDutyModernWarfare3),
584 | "Diablo III / Reaper of Souls" => Ok(BestSellingVideoGame::DiabloIiiReaperOfSouls),
585 | "Duck Hunt" => Ok(BestSellingVideoGame::DuckHunt),
586 | "FIFA 18" => Ok(BestSellingVideoGame::Fifa18),
587 | "Grand Theft Auto IV" => Ok(BestSellingVideoGame::GrandTheftAutoIv),
588 | "Grand Theft Auto V" => Ok(BestSellingVideoGame::GrandTheftAutoV),
589 | "Grand Theft Auto: San Andreas" => Ok(BestSellingVideoGame::GrandTheftAutoSanAndreas),
590 | "Human: Fall Flat" => Ok(BestSellingVideoGame::HumanFallFlat),
591 | "Kinect Adventures!" => Ok(BestSellingVideoGame::KinectAdventures),
592 | "Mario Kart 8 / Deluxe" => Ok(BestSellingVideoGame::MarioKart8Deluxe),
593 | "Mario Kart DS" => Ok(BestSellingVideoGame::MarioKartDs),
594 | "Mario Kart Wii" => Ok(BestSellingVideoGame::MarioKartWii),
595 | "Minecraft" => Ok(BestSellingVideoGame::Minecraft),
596 | "New Super Mario Bros." => Ok(BestSellingVideoGame::NewSuperMarioBros),
597 | "New Super Mario Bros. U / Deluxe / Luigi U" => {
598 | Ok(BestSellingVideoGame::NewSuperMarioBrosUDeluxeLuigiU)
599 | }
600 | "New Super Mario Bros. Wii" => Ok(BestSellingVideoGame::NewSuperMarioBrosWii),
601 | "Nintendogs" => Ok(BestSellingVideoGame::Nintendogs),
602 | "Pac-Man" => Ok(BestSellingVideoGame::PacMan),
603 | "Pokemon Diamond / Pearl / Platinum" => {
604 | Ok(BestSellingVideoGame::PokemonDiamondPearlPlatinum)
605 | }
606 | "Pokemon Gold / Silver / Crystal" => Ok(BestSellingVideoGame::PokemonGoldSilverCrystal),
607 | "Pokemon Red / Green / Blue / Yellow" => {
608 | Ok(BestSellingVideoGame::PokemonRedGreenBlueYellow)
609 | }
610 | "Pokemon Ruby / Sapphire / Emerald" => {
611 | Ok(BestSellingVideoGame::PokemonRubySapphireEmerald)
612 | }
613 | "Pokemon Sun / Moon / Ultra Sun / Ultra Moon" => {
614 | Ok(BestSellingVideoGame::PokemonSunMoonUltraSunUltraMoon)
615 | }
616 | "Pokemon Sword / Shield" => Ok(BestSellingVideoGame::PokemonSwordShield),
617 | "PUBG: Battlegrounds" => Ok(BestSellingVideoGame::PubgBattlegrounds),
618 | "Red Dead Redemption" => Ok(BestSellingVideoGame::RedDeadRedemption),
619 | "Red Dead Redemption 2" => Ok(BestSellingVideoGame::RedDeadRedemption2),
620 | "Sonic the Hedgehog" => Ok(BestSellingVideoGame::SonicTheHedgehog),
621 | "Super Mario 64 / DS" => Ok(BestSellingVideoGame::SuperMario64Ds),
622 | "Super Mario Bros." => Ok(BestSellingVideoGame::SuperMarioBros),
623 | "Super Mario Bros. 3" => Ok(BestSellingVideoGame::SuperMarioBros3),
624 | "Super Mario Odyssey" => Ok(BestSellingVideoGame::SuperMarioOdyssey),
625 | "Super Mario World" => Ok(BestSellingVideoGame::SuperMarioWorld),
626 | "Super Smash Bros. Ultimate" => Ok(BestSellingVideoGame::SuperSmashBrosUltimate),
627 | "Terraria" => Ok(BestSellingVideoGame::Terraria),
628 | "Tetris (EA)" => Ok(BestSellingVideoGame::TetrisEa),
629 | "Tetris (Nintendo)" => Ok(BestSellingVideoGame::TetrisNintendo),
630 | "The Elder Scrolls V: Skyrim" => Ok(BestSellingVideoGame::TheElderScrollsVSkyrim),
631 | "The Legend of Zelda: Breath of the Wild" => {
632 | Ok(BestSellingVideoGame::TheLegendOfZeldaBreathOfTheWild)
633 | }
634 | "The Witcher 3 / Hearts of Stone / Blood and Wine" => {
635 | Ok(BestSellingVideoGame::TheWitcher3HeartsOfStoneBloodAndWine)
636 | }
637 | "Wii Fit / Plus" => Ok(BestSellingVideoGame::WiiFitPlus),
638 | "Wii Play" => Ok(BestSellingVideoGame::WiiPlay),
639 | "Wii Sports" => Ok(BestSellingVideoGame::WiiSports),
640 | "Wii Sports Resort" => Ok(BestSellingVideoGame::WiiSportsResort),
641 | _ => Err(format!("Unknown BestSellingVideoGame {}", s)),
642 | }
643 | }
644 | }
645 | ```
646 |
--------------------------------------------------------------------------------
/example/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 | [lib]
8 | proc-macro = true
9 |
10 | [dependencies]
11 | proc-macro2 = { version = "1.0.51", default-features = false }
12 | quote = "1.0.23"
13 | sea-orm = { version = "1.0.0", features = [
14 | "sqlx-mysql",
15 | "runtime-tokio-rustls",
16 | ] }
17 | serde = { version = "1.0.152", features = ["derive"] }
18 | syn = { version = "1.0.109", features = ["full"] }
19 | symbols = "1.0.0"
20 | tokio = "1.25.0"
21 |
--------------------------------------------------------------------------------
/example/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: "3.3"
2 | services:
3 | rust:
4 | image: "rust:latest"
5 | restart: "no"
6 | depends_on:
7 | - mariadb
8 | working_dir: /app/example
9 | volumes:
10 | - ..:/app
11 | - /app/example/target
12 | environment:
13 | DATABASE_URL: mysql://mariadb:mariadb@mariadb/example
14 | command: "cargo test"
15 | mariadb:
16 | image: "mariadb:latest"
17 | restart: "no"
18 | environment:
19 | MARIADB_ROOT_PASSWORD: reallystrongpassword
20 | MARIADB_USER: mariadb
21 | MARIADB_PASSWORD: mariadb
22 | MARIADB_DATABASE: example
23 | volumes:
24 | - ./fixtures/mariadb:/docker-entrypoint-initdb.d
25 |
--------------------------------------------------------------------------------
/example/fixtures/mariadb/schema.sql:
--------------------------------------------------------------------------------
1 |
2 | DROP TABLE IF EXISTS `best_selling_video_games`;
3 |
4 | CREATE TABLE `best_selling_video_games` (
5 | `rank` tinyint(2) NOT NULL,
6 | `name` varchar(255) NOT NULL,
7 | `sales` varchar(255) NOT NULL,
8 | `series` varchar(255) NOT NULL,
9 | `platforms` varchar(255) NOT NULL,
10 | `initial_release_date` varchar(255) NOT NULL,
11 | `developer` varchar(255) NOT NULL,
12 | `publisher` varchar(255) NOT NULL,
13 | PRIMARY KEY (`name`)
14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
15 |
16 | -- list taken from https://en.wikipedia.org/wiki/List_of_best-selling_video_games
17 | -- normalized with regexp ^(\d+)\s+\t([^\t]+)\s+\t([\d,]+)\s+\t([^\t]+)\s+\t([^\t]+)\s+\t([^\t]+)\s+\t([^\t]+)\s+\t([^\t]+)\s+\t$
18 | INSERT INTO `best_selling_video_games` VALUES
19 | (1, 'Minecraft', '238,000,000', 'Minecraft', 'Multi-platform', 'November 18, 2011', 'Mojang Studios', 'Xbox Game Studios'),
20 | (2, 'Grand Theft Auto V', '160,000,000', 'Grand Theft Auto', 'Multi-platform', 'September 17, 2013', 'Rockstar North', 'Rockstar Games'),
21 | (3, 'Tetris (EA)', '100,000,000', 'Tetris', 'Multi-platform', 'September 12, 2006', 'EA Mobile', 'Electronic Arts'),
22 | (4, 'Wii Sports', '82,900,000', 'Wii', 'Wii', 'November 19, 2006', 'Nintendo EAD', 'Nintendo'),
23 | (5, 'PUBG: Battlegrounds', '75,000,000', 'PUBG Universe', 'Multi-platform', 'December 20, 2017', 'PUBG Corporation', 'PUBG Corporation'),
24 | (6, 'Super Mario Bros.', '58,000,000', 'Super Mario', 'Multi-platform', 'September 13, 1985', 'Nintendo R&D4', 'Nintendo'),
25 | (7, 'Mario Kart 8 / Deluxe', '51,810,000', 'Mario Kart', 'Wii U / Switch', 'May 29, 2014', 'Nintendo EAD', 'Nintendo'),
26 | (8, 'Pokemon Red / Green / Blue / Yellow', '47,520,000', 'Pokemon', 'Game Boy / Color', 'February 27, 1996', 'Game Freak', 'Nintendo'),
27 | (9, 'Terraria', '44,000,000', 'None', 'Multi-platform', 'May 16, 2011', 'Re-Logic', 'Re-Logic / 505 Games'),
28 | (10, 'Wii Fit / Plus', '43,800,000', 'Wii', 'Wii', 'December 1, 2007', 'Nintendo EAD', 'Nintendo'),
29 | (11, 'Red Dead Redemption 2', '43,000,000', 'Red Dead', 'Multi-platform', 'October 26, 2018', 'Rockstar Studios', 'Rockstar Games'),
30 | (11, 'Tetris (Nintendo)', '43,000,000', 'Tetris', 'Game Boy / NES', 'June 14, 1989', 'Nintendo R&D1', 'Nintendo'),
31 | (13, 'Pac-Man', '42,071,635', 'Pac-Man', 'Multi-platform', 'May 22, 1980', 'Namco', 'Namco'),
32 | (14, 'The Witcher 3 / Hearts of Stone / Blood and Wine', '40,000,000', 'The Witcher', 'Multi-platform', 'May 19, 2015', 'CD Projekt Red', 'CD Projekt'),
33 | (15, 'Animal Crossing: New Horizons', '37,620,000', 'Animal Crossing', 'Nintendo Switch', 'March 20, 2020', 'Nintendo EPD', 'Nintendo'),
34 | (16, 'Mario Kart Wii', '37,380,000', 'Mario Kart', 'Wii', 'April 10, 2008', 'Nintendo EAD', 'Nintendo'),
35 | (17, 'Wii Sports Resort', '33,140,000', 'Wii', 'Wii', 'June 25, 2009', 'Nintendo EAD', 'Nintendo'),
36 | (18, 'New Super Mario Bros.', '30,800,000', 'Super Mario', 'Nintendo DS', 'May 15, 2006', 'Nintendo EAD', 'Nintendo'),
37 | (19, 'New Super Mario Bros. Wii', '30,320,000', 'Super Mario', 'Wii', 'November 11, 2009', 'Nintendo EAD', 'Nintendo'),
38 | (20, 'The Elder Scrolls V: Skyrim', '30,000,000', 'The Elder Scrolls', 'Multi-platform', 'November 11, 2011', 'Bethesda Game Studios', 'Bethesda Softworks'),
39 | (20, 'Call of Duty: Modern Warfare', '30,000,000', 'Call of Duty', 'Multi-platform', 'October 25, 2019', 'Infinity Ward', 'Activision'),
40 | (20, 'Diablo III / Reaper of Souls', '30,000,000', 'Diablo', 'Multi-platform', 'May 16, 2012', 'Blizzard Entertainment', 'Blizzard Entertainment'),
41 | (20, 'Human: Fall Flat', '30,000,000', 'None', 'Multi-platform', 'July 22, 2016', 'No Brakes Games', 'Curve Digital'),
42 | (24, 'Pokemon Gold / Silver / Crystal', '29,490,000', 'Pokemon', 'Game Boy Color', 'November 21, 1999', 'Game Freak', 'Nintendo'),
43 | (25, 'Duck Hunt', '28,300,000', 'None', 'NES', 'April 21, 1984', 'Nintendo R&D1', 'Nintendo'),
44 | (26, 'Wii Play', '28,020,000', 'Wii', 'Wii', 'December 2, 2006', 'Nintendo EAD', 'Nintendo'),
45 | (27, 'Grand Theft Auto: San Andreas', '27,500,000', 'Grand Theft Auto', 'Multi-platform', 'October 26, 2004', 'Rockstar North', 'Rockstar Games'),
46 | (28, 'The Legend of Zelda: Breath of the Wild', '27,490,000', 'The Legend of Zelda', 'Wii U / Switch', 'March 3, 2017', 'Nintendo EPD', 'Nintendo'),
47 | (29, 'Super Smash Bros. Ultimate', '27,400,000', 'Super Smash Bros.', 'Nintendo Switch', 'December 7, 2018', 'Bandai Namco Studios / Sora Ltd.', 'Nintendo'),
48 | (30, 'Super Mario World', '26,662,500', 'Super Mario', 'Multi-platform', 'November 21, 1990', 'Nintendo EAD', 'Nintendo'),
49 | (31, 'Call of Duty: Modern Warfare 3', '26,500,000', 'Call of Duty', 'Multi-platform', 'November 8, 2011', 'Infinity Ward / Sledgehammer', 'Activision'),
50 | (32, 'Call of Duty: Black Ops', '26,200,000', 'Call of Duty', 'Multi-platform', 'November 9, 2010', 'Treyarch', 'Activision'),
51 | (33, 'Borderlands 2', '26,000,000', 'Borderlands', 'Multi-platform', 'September 18, 2012', 'Gearbox Software', '2K Games'),
52 | (34, 'Pokemon Sun / Moon / Ultra Sun / Ultra Moon', '25,310,000', 'Pokemon', 'Nintendo 3DS', 'November 18, 2016', 'Game Freak', 'Nintendo / The Pokemon Company'),
53 | (35, 'Grand Theft Auto IV', '25,000,000', 'Grand Theft Auto', 'Multi-platform', 'April 29, 2008', 'Rockstar North', 'Rockstar Games'),
54 | (36, 'Pokemon Diamond / Pearl / Platinum', '24,730,000', 'Pokemon', 'Nintendo DS', 'September 28, 2006', 'Game Freak', 'Nintendo / The Pokemon Company'),
55 | (37, 'Super Mario Bros. 3', '24,430,000', 'Super Mario', 'Multi-platform', 'October 23, 1988', 'Nintendo EAD', 'Nintendo'),
56 | (38, 'Call of Duty: Black Ops II', '24,200,000', 'Call of Duty', 'Multi-platform', 'November 12, 2012', 'Treyarch', 'Activision'),
57 | (39, 'Kinect Adventures!', '24,000,000', 'None', 'Xbox 360', 'November 4, 2010', 'Good Science Studio', 'Xbox Game Studios'),
58 | (39, 'FIFA 18', '24,000,000', 'FIFA', 'Multi-platform', 'September 29, 2017', 'EA Vancouver', 'EA Sports'),
59 | (41, 'Sonic the Hedgehog', '23,982,960', 'Sonic the Hedgehog', 'Multi-platform', 'June 23, 1991', 'Sonic Team', 'Sega'),
60 | (42, 'Nintendogs', '23,960,000', 'None', 'Nintendo DS', 'April 21, 2005', 'Nintendo EAD', 'Nintendo'),
61 | (43, 'Pokemon Sword / Shield', '23,900,000', 'Pokemon', 'Nintendo Switch', 'November 15, 2019', 'Game Freak', 'Nintendo / The Pokemon Company'),
62 | (44, 'Mario Kart DS', '23,600,000', 'Mario Kart', 'Nintendo DS', 'November 14, 2005', 'Nintendo EAD', 'Nintendo'),
63 | (45, 'Super Mario Odyssey', '23,020,000', 'Super Mario', 'Nintendo Switch', 'October 27, 2017', 'Nintendo EPD', 'Nintendo'),
64 | (46, 'Red Dead Redemption', '23,000,000', 'Red Dead', 'PS3 / Xbox 360', 'May 18, 2010', 'Rockstar San Diego', 'Rockstar Games'),
65 | (47, 'Super Mario 64 / DS', '22,960,000', 'Super Mario', 'Nintendo 64 / DS', 'June 23, 1996', 'Nintendo EAD', 'Nintendo'),
66 | (48, 'Call of Duty: Modern Warfare 2', '22,700,000', 'Call of Duty', 'Multi-platform', 'November 10, 2009', 'Infinity Ward', 'Activision'),
67 | (49, 'Pokemon Ruby / Sapphire / Emerald', '22,540,000', 'Pokemon', 'Game Boy Advance', 'November 21, 2002', 'Game Freak', 'Nintendo / The Pokemon Company'),
68 | (50, 'New Super Mario Bros. U / Deluxe / Luigi U', '21,600,000', 'Super Mario', 'Wii U / Nintendo Switch', 'November 18, 2012', 'Nintendo EAD', 'Nintendo');
69 |
--------------------------------------------------------------------------------
/example/src/lib.rs:
--------------------------------------------------------------------------------
1 | use std::time::Duration;
2 |
3 | use proc_macro2::{Span, TokenStream};
4 |
5 | use sea_orm::{ConnectOptions, Database, DatabaseConnection};
6 |
7 | use syn::{parse_macro_input, AttributeArgs, ItemEnum, Lit, Meta, NestedMeta};
8 |
9 | use symbols::symbols;
10 |
11 | mod model;
12 |
13 | #[proc_macro_attribute]
14 | pub fn example(
15 | args: proc_macro::TokenStream,
16 | input: proc_macro::TokenStream,
17 | ) -> proc_macro::TokenStream {
18 | let mut item = parse_macro_input!(input as ItemEnum);
19 | let args = parse_macro_input!(args as AttributeArgs);
20 |
21 | get_enum(&mut item, &args)
22 | .unwrap_or_else(syn::Error::into_compile_error)
23 | .into()
24 | }
25 |
26 | async fn get_conn() -> syn::Result {
27 | let url = std::env::var("DATABASE_URL").map_err(|e| syn::Error::new(Span::call_site(), e))?;
28 | let mut options = ConnectOptions::new(url);
29 | options
30 | .min_connections(1)
31 | .max_connections(1)
32 | .connect_timeout(Duration::from_secs(1))
33 | .idle_timeout(Duration::from_secs(1));
34 | Database::connect(options)
35 | .await
36 | .map_err(|e| syn::Error::new(Span::call_site(), e))
37 | }
38 |
39 | fn get_enum(item: &mut ItemEnum, args: &[NestedMeta]) -> syn::Result {
40 | // search for table, simply #[macro(table = "table_name")]
41 | let table = args
42 | .iter()
43 | .find_map(|arg| {
44 | if let NestedMeta::Meta(Meta::NameValue(mv)) = arg {
45 | if mv.path.is_ident("table") {
46 | if let Lit::Str(s) = &mv.lit {
47 | return Some(s.value());
48 | }
49 | }
50 | }
51 | None
52 | })
53 | .ok_or_else(|| syn::Error::new(Span::call_site(), "Missing table attribute"))?;
54 |
55 | // start an async runtime to be able to use sea-orm
56 | tokio::runtime::Builder::new_current_thread()
57 | .enable_all()
58 | .build()
59 | .unwrap()
60 | .block_on(async move {
61 | match table.as_str() {
62 | "best_selling_video_games" => {
63 | symbols::(item, args, get_conn).await
64 | }
65 | _ => Err(syn::Error::new(
66 | Span::call_site(),
67 | format!("Unrecognized table \"{}\"", table),
68 | )),
69 | }
70 | })
71 | }
72 |
--------------------------------------------------------------------------------
/example/src/model.rs:
--------------------------------------------------------------------------------
1 | use sea_orm::entity::prelude::*;
2 |
3 | use serde::{Deserialize, Serialize};
4 |
5 | use symbols::EntityFilter;
6 |
7 | #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)]
8 | #[sea_orm(table_name = "best_selling_video_games")]
9 | pub struct Model {
10 | pub rank: i8,
11 | #[sea_orm(primary_key, auto_increment = false)]
12 | pub name: String,
13 | pub sales: String,
14 | pub series: String,
15 | pub platforms: String,
16 | pub initial_release_date: String,
17 | pub developer: String,
18 | pub publisher: String,
19 | }
20 |
21 | #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
22 | pub enum Relation {}
23 |
24 | impl ActiveModelBehavior for ActiveModel {}
25 |
26 | impl EntityFilter for Entity {}
27 |
28 | impl PartialEq for Column {
29 | fn eq(&self, other: &Self) -> bool {
30 | matches!(
31 | (self, other),
32 | (Column::Rank, Column::Rank)
33 | | (Column::Name, Column::Name)
34 | | (Column::Sales, Column::Sales)
35 | | (Column::Series, Column::Series)
36 | | (Column::Platforms, Column::Platforms)
37 | | (Column::InitialReleaseDate, Column::InitialReleaseDate)
38 | | (Column::Developer, Column::Developer)
39 | | (Column::Publisher, Column::Publisher)
40 | )
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/example/tests/it_works.rs:
--------------------------------------------------------------------------------
1 | use std::fmt;
2 |
3 | use sea_orm::{EnumIter, Iterable};
4 |
5 | #[example::example(
6 | table = "best_selling_video_games",
7 | platforms(type = "Platforms", fn = "from_str"),
8 | developer = "Developer",
9 | publisher(type = "Publisher", fn = "from_str")
10 | )]
11 | #[derive(Debug, EnumIter)]
12 | pub enum BestSellingVideoGame {}
13 |
14 | #[derive(Debug)]
15 | pub enum Platform {
16 | MultiPlatform,
17 | NintendoSwitch,
18 | Nes,
19 | Xbox360,
20 | NintendoDs,
21 | Wii,
22 | WiiU,
23 | Ps2,
24 | GameBoyColor,
25 | GameBoyAdvance,
26 | Nintendo3ds,
27 | Nintendo64,
28 | GameBoy,
29 | }
30 |
31 | pub struct Platforms(&'static [Platform]);
32 |
33 | impl Platforms {
34 | const fn from_str(s: &'static str) -> Self {
35 | match s.as_bytes() {
36 | b"Game Boy Advance" => Platforms(&[Platform::GameBoyAdvance]),
37 | b"Game Boy / Color" => Platforms(&[Platform::GameBoy, Platform::GameBoyColor]),
38 | b"Game Boy Color" => Platforms(&[Platform::GameBoyColor]),
39 | b"Game Boy / NES" => Platforms(&[Platform::GameBoy, Platform::Nes]),
40 | b"Multi-platform" => Platforms(&[Platform::MultiPlatform]),
41 | b"NES" => Platforms(&[Platform::Nes]),
42 | b"Nintendo 3DS" => Platforms(&[Platform::Nintendo3ds]),
43 | b"Nintendo 64 / DS" => Platforms(&[Platform::Nintendo64, Platform::NintendoDs]),
44 | b"Nintendo DS" => Platforms(&[Platform::NintendoDs]),
45 | b"Nintendo Switch" => Platforms(&[Platform::NintendoSwitch]),
46 | b"PS3 / Xbox 360" => Platforms(&[Platform::Ps2, Platform::Xbox360]),
47 | b"Wii" => Platforms(&[Platform::Wii]),
48 | b"Wii U / Nintendo Switch" | b"Wii U / Switch" => {
49 | Platforms(&[Platform::WiiU, Platform::NintendoSwitch])
50 | }
51 | b"Xbox 360" => Platforms(&[Platform::Xbox360]),
52 | _ => unreachable!(),
53 | }
54 | }
55 | }
56 |
57 | impl fmt::Debug for Platforms {
58 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 | write!(f, "{:?}", self.0)
60 | }
61 | }
62 |
63 | #[derive(Debug)]
64 | pub enum Developer {
65 | BandaiNamcoStudiosSoraLtd,
66 | BethesdaGameStudios,
67 | BlizzardEntertainment,
68 | CdProjektRed,
69 | EaMobile,
70 | EaVancouver,
71 | GameFreak,
72 | GearboxSoftware,
73 | GoodScienceStudio,
74 | InfinityWard,
75 | InfinityWardSledgehammer,
76 | MojangStudios,
77 | Namco,
78 | NintendoEad,
79 | NintendoEpd,
80 | NintendoRD1,
81 | NintendoRD4,
82 | NoBrakesGames,
83 | PubgCorporation,
84 | ReLogic,
85 | RockstarNorth,
86 | RockstarSanDiego,
87 | RockstarStudios,
88 | SonicTeam,
89 | Treyarch,
90 | }
91 |
92 | #[derive(Debug)]
93 | pub enum Publisher {
94 | TwoKGames,
95 | Activision,
96 | BethesdaSoftworks,
97 | BlizzardEntertainment,
98 | CdProjekt,
99 | CurveDigital,
100 | EaSports,
101 | ElectronicArts,
102 | Namco,
103 | Nintendo,
104 | NintendoThePokemonCompany,
105 | PubgCorporation,
106 | ReLogic505Games,
107 | RockstarGames,
108 | Sega,
109 | XboxGameStudios,
110 | }
111 |
112 | impl Publisher {
113 | const fn from_str(s: &'static str) -> Self {
114 | match s.as_bytes() {
115 | b"2K Games" => Publisher::TwoKGames,
116 | b"Activision" => Publisher::Activision,
117 | b"Bethesda Softworks" => Publisher::BethesdaSoftworks,
118 | b"Blizzard Entertainment" => Publisher::BlizzardEntertainment,
119 | b"CD Projekt" => Publisher::CdProjekt,
120 | b"Curve Digital" => Publisher::CurveDigital,
121 | b"EA Sports" => Publisher::EaSports,
122 | b"Electronic Arts" => Publisher::ElectronicArts,
123 | b"Namco" => Publisher::Namco,
124 | b"Nintendo" => Publisher::Nintendo,
125 | b"Nintendo / The Pokemon Company" => Publisher::NintendoThePokemonCompany,
126 | b"PUBG Corporation" => Publisher::PubgCorporation,
127 | b"Re-Logic / 505 Games" => Publisher::ReLogic505Games,
128 | b"Rockstar Games" => Publisher::RockstarGames,
129 | b"Sega" => Publisher::Sega,
130 | b"Xbox Game Studios" => Publisher::XboxGameStudios,
131 | _ => unreachable!(),
132 | }
133 | }
134 | }
135 |
136 | #[test]
137 | fn it_works() {
138 | for game in BestSellingVideoGame::iter() {
139 | println!(
140 | "rank: {}, name: {} sales: {} series: {} platforms: {:?} initial release date: {} developer: {:?} publisher: {:?}",
141 | game.rank(),
142 | game.as_str(),
143 | game.sales(),
144 | game.series(),
145 | game.platforms(),
146 | game.initial_release_date(),
147 | game.developer(),
148 | game.publisher()
149 | );
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/img/meme.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nappa85/symbols/48a529ab99ce9a1e9adfe18ffad0f98a31d7d2e6/img/meme.jpg
--------------------------------------------------------------------------------
/symbols-models/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "symbols-models"
3 | version = "1.0.0"
4 | edition = "2021"
5 | authors = ["Marco Napetti"]
6 | repository = "https://github.com/nappa85/symbols"
7 | documentation = "https://docs.rs/symbols-models"
8 | readme = "../README.md"
9 | license = "WTFPL"
10 | description = "Proc-macro utility to populate enums from database data (shared traits)"
11 | categories = [
12 | "data-structures",
13 | "development-tools::procedural-macro-helpers",
14 | "database",
15 | ]
16 | keywords = ["proc-macro", "enum", "database"]
17 |
18 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
19 |
20 | [dependencies]
21 | sea-orm = "1.0.0"
22 |
--------------------------------------------------------------------------------
/symbols-models/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![deny(warnings)]
2 | #![deny(missing_docs)]
3 |
4 | //! # Symbols-models
5 | //!
6 | //! Shared traits from Symbols proc-macro-utility, to be able to share models between macros and real applications.
7 |
8 | use sea_orm::{
9 | sea_query::{Expr, SimpleExpr},
10 | EntityTrait,
11 | };
12 |
13 | /// This trait allows data filtering on macro execution
14 | /// It's default implementation simply adds WHERE 1 = 1 to data retrieve query
15 | ///
16 | /// Since only basic types are supported, it's important to use only basic types in models.
17 | pub trait EntityFilter: EntityTrait + Default {
18 | /// Returned expression in injected in data retrieve query to allow data filtering
19 | fn filter() -> SimpleExpr {
20 | Expr::val(1).eq(1)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/symbols/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "symbols"
3 | version = "1.0.0"
4 | edition = "2021"
5 | authors = ["Marco Napetti"]
6 | repository = "https://github.com/nappa85/symbols"
7 | documentation = "https://docs.rs/symbols"
8 | readme = "../README.md"
9 | license = "WTFPL"
10 | description = "Proc-macro utility to populate enums from database data"
11 | categories = [
12 | "data-structures",
13 | "development-tools::procedural-macro-helpers",
14 | "database",
15 | ]
16 | keywords = ["proc-macro", "enum", "database"]
17 |
18 | [dependencies]
19 | bincode = "1.3.3"
20 | heck = "0.5.0"
21 | itertools = "0.13.0"
22 | proc-macro2 = { version = "1.0.51", default-features = false }
23 | quote = "1.0.23"
24 | sea-orm = "1.0.0"
25 | serde = "1.0.152"
26 | syn = { version = "1.0.109", features = ["full"] }
27 | symbols-models = "1.0.0"
28 | tracing = "0.1.37"
29 |
--------------------------------------------------------------------------------
/symbols/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![deny(warnings)]
2 | #![deny(missing_docs)]
3 |
4 | //! # Symbols
5 | //!
6 | //! This is an utility to build a proc-macro that connects to a database, retrieves data from given table and populates an enum variants with primary keys values
7 | //! It also generates a method for every non-primary-key field, and, when there are multiple primary keys, a costructor for every possible subset of primary keys
8 |
9 | use std::{collections::HashMap, env, fs, future::Future, io};
10 |
11 | use heck::{ToSnakeCase, ToUpperCamelCase};
12 |
13 | use itertools::Itertools;
14 |
15 | use proc_macro2::{Ident, Literal, Span, TokenStream};
16 |
17 | use quote::quote;
18 |
19 | use sea_orm::{
20 | DatabaseConnection, EntityName, EntityTrait, Iterable, ModelTrait, PrimaryKeyToColumn, QueryFilter, Value,
21 | };
22 |
23 | use serde::{de::DeserializeOwned, Serialize};
24 |
25 | pub use symbols_models::EntityFilter;
26 |
27 | use syn::{punctuated::Punctuated, token::Comma, Fields, ItemEnum, Lit, LitBool, Meta, NestedMeta, Variant};
28 |
29 | use tracing::{error, info};
30 |
31 | /// Main function
32 | /// Given a database model (via generics), an enum item, a list of arguments and an async function to retrieve a database connection
33 | /// it populates the enum using primary key(s) values.
34 | /// Only string-typed primary keys are supported.
35 | ///
36 | /// When a single primary key is present, it simply generate an as_str method and a TryFrom<&str> implementation.
37 | /// When multiple primary keys are present, it generates a costructor for every possible subset of primary keys.
38 | ///
39 | /// For every non-primary key field of a supported type, it generates a const method to retrieve it.
40 | ///
41 | /// Replacements can be done on every string-typed field, even primary keys, and are done using annotated parameters.
42 | /// Two type of replacements are supported:
43 | /// * basic: written in the form #[macro(field = "enum")] or #[macro(field(type = "enum"))], where we are telling to replace string values from `field` with variants from enum `enum`, variant names will be the CamelCase version of field value.
44 | /// * advanced: written in the form #[macro(field(type = "bar", fn = "foo"))], where we are telling to replace string values from `field` with a call to method `foo` from struct/enum `bar`, method output is expected to be of type `bar`.
45 | pub async fn symbols(item: &mut ItemEnum, args: &[NestedMeta], get_conn: F) -> syn::Result
46 | where
47 | M: EntityTrait + EntityFilter + Default,
48 | ::Model: Serialize + DeserializeOwned,
49 | ::Column: PartialEq,
50 | F: Fn() -> Fut,
51 | Fut: Future