Skip to main content

ronky/
lib.rs

1#![allow(clippy::multiple_crate_versions)]
2
3//! # ๐Ÿฑ RONKY ๐Ÿฑ
4//!
5//! [![Crates.io Version](https://img.shields.io/crates/v/ronky)](https://crates.io/crates/ronky)
6//! [![Purrs Per Minute](https://img.shields.io/badge/purrs-over%209000-orange)](https://github.com/modiimedia/arri)
7//! [![Cat Approved](https://img.shields.io/badge/cat-approved-brightgreen)](https://github.com/modiimedia/arri)
8//! [![Rustacean Friendly](https://img.shields.io/badge/rustacean-friendly-blue)](https://github.com/modiimedia/arri)
9//!
10//! _"Converting Rust types shouldn't be this purr-fect, but here we are..."_
11//!
12//! ## ๐Ÿ˜บ What in the Whiskers is Ronky?
13//!
14//! Imagine if your Rust types could speak other languages without learning a single foreign word.
15//! That's Ronky โ€“ your code's personal polyglot translator that speaks fluent
16//! [Arri](https://github.com/modiimedia/arri), turning your carefully crafted Rust types into
17//! schemas that even JavaScript developers can understand.
18//!
19//! Born from the frustration of manual schema creation (and named after a particularly vocal cat),
20//! Ronky does the tedious work so you can focus on the important stuff โ€“ like deciding whether your
21//! next variable should be called `data` or `info` (we both know you'll pick `data`).
22//!
23//! > ๐Ÿšง **Paws at Work**: Like a cat that's not quite finished knocking everything off your desk,
24//! > Ronky is still under construction. Object serialization and deserialization are coming soon,
25//! > probably right after this catnap. ๐Ÿšง
26//!
27//! ## โœจ Features That Make You Go "Meow!"
28//!
29//! Ronky doesn't just toss your types over the fence to Arri-land. It crafts them with the same
30//! attention to detail that a cat gives to knocking your most precious possessions off shelves:
31//!
32//! ```text
33//! โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
34//! โ”‚                          RONKY'S REPERTOIRE                           โ”‚
35//! โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
36//! โ”‚ ๐Ÿงฌ Type Wizardry          โ”‚ - Transforms primitives with grace        โ”‚
37//! โ”‚                           โ”‚ - Handles generic types without whining   โ”‚
38//! โ”‚                           โ”‚ - Makes associated types feel welcome     โ”‚
39//! โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
40//! โ”‚ ๐Ÿงฉ Collection Conjuring   โ”‚ - Vectors become elegant "elements"       โ”‚
41//! โ”‚                           โ”‚ - Maps manifest as "values" schemas       โ”‚
42//! โ”‚                           โ”‚ - Optional types know when to disappear   โ”‚
43//! โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
44//! โ”‚ ๐Ÿ›ก๏ธ Guardian Features      โ”‚ - Strict mode keeps schemas pristine      โ”‚
45//! โ”‚                           โ”‚ - Discriminators tag unions properly      โ”‚
46//! โ”‚                           โ”‚ - Circular refs handled without dizziness โ”‚
47//! โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
48//! โ”‚ ๐Ÿ”„ Transformation Magic   โ”‚ - Case transformations (snake โ†’ UPPER)    โ”‚
49//! โ”‚                           โ”‚ - Field renaming for multilingual joy     โ”‚
50//! โ”‚                           โ”‚ - Nullable marking for optional presence  โ”‚
51//! โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
52//! โ”‚ ๐Ÿ“ Documentation Delight  โ”‚ - Comments become documentation           โ”‚
53//! โ”‚                           โ”‚ - Deprecation warnings that don't nag     โ”‚
54//! โ”‚                           โ”‚ - Metadata that brings joy to readers     โ”‚
55//! โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
56//! ```
57//!
58//! With Ronky, your type schema generation is both:
59//! 1. **Compile-time verified** - Errors at compile time, not at 3 AM when you're deploying
60//! 2. **Automatically generated** - Because life's too short to manually update schemas
61//!
62//! > ๐Ÿ’ก **Pro Tip**: Ronky's powers grow with your documentation. The more doc comments you add,
63//! > the more magnificent your schemas become. It's like feeding treats to a cat โ€“ the rewards
64//! > are well worth it.
65//!
66//! ## ๐Ÿค The Cool Cats Club (Compatible Crates)
67//!
68//! Ronky has an extensive social network. Think of these crates as the neighborhood cats that
69//! regularly visit your backyard โ€“ they're all welcome and get special treatment:
70//!
71//! ```text
72//! TEMPORAL FRIENDS         ๐Ÿ•ฐ๏ธ  chrono, time
73//! IDENTITY SPECIALISTS     ๐Ÿชช  uuid
74//! BIG NUMBER EXPERTS       ๐Ÿ”ข  bigdecimal, num-bigint, num-bigfloat
75//! PRECISION MASTERS        ๐Ÿ’ฐ  rust_decimal, decimal
76//! WEB-SAVVY NAVIGATORS     ๐ŸŒ  url
77//! DATA-HANDLING WIZARDS    ๐Ÿ“Š  bytes
78//! CONCURRENT COMPANIONS    ๐Ÿงต  dashmap
79//! OPTIMIZED PERFORMERS     โšก  smallvec
80//! ```
81//!
82//! Each of these crates gets the VIP (Very Important Purring) treatment from Ronky. Their types
83//! are handled with the care and respect they deserve.
84//!
85//! > ๐Ÿˆ **Missing your favorite companion?** Open an issue to suggest a new addition to Ronky's
86//! > compatible crates collection. The more the merrier!
87//!
88//! ## ๐Ÿ‘จโ€๐Ÿ’ป The Story Behind Ronky
89//!
90//! Let me share the real origin story โ€“ Ronky wasn't born from late-night caffeine-fueled frustration
91//! (though there's been plenty of that in my coding career). It all started when a friend dropped a
92//! Discord message with a link to the [Arri project](https://github.com/modiimedia/arri). One look at
93//! what Arri was doing with type conversions and I was hooked.
94//!
95//! As a passionate Rustacean, I immediately thought: "This is brilliant! But it needs Rust support."
96//! And thus Ronky was born โ€“ creating a bridge between the elegant type system of Rust and the universal
97//! schema language of Arri.
98//!
99//! I named it after my cat not just because he was adorable (though he absolutely was), but because
100//! he embodied what good libraries should be โ€“ helpful, reliable, and occasionally surprising you
101//! with something delightful. Like Ronky the cat finding innovative ways to get treats without
102//! moving, Ronky the library finds ways to update your API schemas without you lifting a finger.
103//!
104//! My hope is that this library saves you time, prevents those pesky "the API contract changed but
105//! the docs didn't" bugs, and maybe โ€“ just maybe โ€“ frees up enough of your day to spend time with
106//! your own four-legged friend (or fish, or rubber duck - whatever brings you joy).
107//!
108//! ## ๐Ÿ“š The Illustrated Guide to Ronky
109//!
110//! ### ๐Ÿ”„ The Basic Transformation
111//!
112//! ```rust,ignore
113//! use ronky::{Exportable, Exported, SCHEMA_VERSION};
114//! use serde_json::{Value, from_str, to_string_pretty};
115//!
116//! // Just add water (and a derive macro)
117//! #[derive(Exported)]
118//! #[arri(transform = "uppercase")] // LOUD NOISES
119//! enum Result<T: Exportable, E: Exportable> {
120//!     /// When things go right (rarely, if you're me)
121//!     Ok(T),
122//!     /// When things go wrong (my default state)
123//!     Err(E),
124//! }
125//!
126//!
127//! // Announce our intentions to the world
128//! println!("๐Ÿงช Creating an Arri {} schema and hoping for the best...", SCHEMA_VERSION);
129//!
130//! // The cat-alchemy happens here
131//! let schema_json = Result::<String, ()>::export()
132//!     .serialize()
133//!     .expect("this to work (please, I have deadlines)");
134//!
135//! // Humans like pretty things
136//! let pretty_json = to_string_pretty(&from_str::<Value>(&schema_json).unwrap()).unwrap();
137//!
138//! // Admire our handiwork
139//! println!("{}", pretty_json);
140//!
141//! // Now go make a cup of tea, you've earned it
142//! ```
143//!
144//! ### ๐Ÿงฉ The Advanced Cat-egory: Building Complex Types
145//!
146//! ```rust,ignore
147//! use ronky::{Exportable, Exported, SCHEMA_VERSION};
148//!
149//! /// Metadata about things (and sometimes other things)
150//! #[derive(Exported)]
151//! struct About<T: Exportable> {
152//!     /// What we called it before marketing got involved
153//!     #[deprecated(since = "1.0.0", note = "Use `firstName` and `lastName` instead")]
154//!     name: String,
155//!
156//!     /// The name that appears on your coffee cup at Starbucks
157//!     first_name: String,
158//!
159//!     /// The name your parents use when you're in trouble
160//!     last_name: Option<String>,
161//!
162//!     /// The number that makes you sigh at birthday parties
163//!     age: u32,
164//!
165//!     /// The subject of our obsession
166//!     of: T,
167//! }
168//!
169//! /// A creature that creates Rust crates, ironically
170//! #[derive(Exported)]
171//! #[arri(strict)] // No surprises allowed! Like a cat with a cucumber
172//! struct Human {
173//!     /// Fellow code-monkeys who review your PRs
174//!     friends: Vec<Human>, // Recursive types? No problem!
175//!
176//!     /// The real owners of your home
177//!     pets: Vec<About<Pet>>,
178//! }
179//!
180//! /// Fashion choices for the discerning feline
181//! #[derive(Exported)]
182//! #[arri(transform = ["snake_case", "uppercase"])] // MULTI_STYLE_TRANSFORMATION
183//! enum CatColor {
184//!     /// Like my coffee and my humor
185//!     Black,
186//!
187//!     /// Like my documentation standards and error handling
188//!     White,
189//!
190//!     /// Like my moral compass when it comes to optimization
191//!     Gray,
192//!
193//!     /// Like my commit history after a weekend hackathon
194//!     MixedGrayWhite,
195//! }
196//!
197//! /// Entities that interrupt your Zoom calls at the worst possible moment
198//! #[derive(Exported)]
199//! #[arri(transform = "uppercase", discriminator = "species")]
200//! enum Pet {
201//!     Dog {
202//!         /// The word you'll repeat 37 times at the dog park
203//!         name: String,
204//!
205//!         /// What you'll forget when the vet asks
206//!         #[arri(nullable)]
207//!         breed: Option<String>,
208//!     },
209//!
210//!     #[arri(rename = "cat")] // All hail the cat overlords!
211//!     Lion {
212//!         /// A suggestion they might consider responding to someday
213//!         name: String,
214//!
215//!         /// Their royal garment
216//!         #[arri(nullable)]
217//!         color: Option<CatColor>,
218//!     },
219//! }
220//! ```
221//!
222//! > ๐Ÿ”ฅ **Hot Tip**: These examples aren't just decorative โ€“ they're functional!
223//! > Copy, paste, and experience the magic of Ronky firsthand. Your future self
224//! > will thank you when your API documentation is automatically up-to-date.
225//!
226//! ## ๐Ÿˆ The Ronky Memorial Section
227//!
228//! ```text
229//!      /\_/\
230//!     ( o.o )
231//!      > ^ <
232//!     /  O  \  "Meow meow, transform types meow."
233//!                                     - Ronky (2010-2024)
234//! ```
235//!
236//! This library immortalizes a magnificent cat named Ronky, whose thunderous purrs
237//! (or "ronks" in Dutch) could wake the neighbors. For 14 remarkable years, this
238//! whiskered genius supervised everything that happened in the house.
239//!
240//! Despite battling acromegaly, Ronky maintained a proud dignity and an uncanny ability
241//! to walk across keyboards. His legacy continues in this library!
242//!
243//! Ronky taught me important programming principles:
244//!
245//! - **Persistence**: If at first you don't succeed, meow louder until someone fixes it for you
246//! - **Efficiency**: Why do something yourself when you can delegate?
247//! - **Work-Life Balance**: No bug is so important that it can't wait until after a nap
248//! - **Code Reviews**: Sometimes the best feedback is just silently judging from a distance
249//!
250//! This library aims to embody these principles by automating the tedious parts of
251//! API development so you can focus on the parts that matter โ€“ like figuring out why
252//! your application works in development but not production (it's always CORS).
253//!
254//! ## ๐Ÿ“‹ Quick Reference
255//!
256//! ### The Basics
257//!
258//! 1. Add `ronky` to your `Cargo.toml`:
259//!    ```toml
260//!    [dependencies]
261//!    ronky = "1.0.0"  # Check crates.io for the latest version
262//!    ```
263//!
264//! 2. Import the essentials:
265//!    ```rust,ignore
266//!    use ronky::{Exported, SCHEMA_VERSION};
267//!    ```
268//!
269//! 3. Decorate your types:
270//!    ```rust,ignore
271//!    #[derive(Exported)]
272//!    struct MyType { /* fields */ }
273//!    ```
274//!
275//! 4. Export and serialize:
276//!    ```rust,ignore
277//!    let schema = MyType::export().serialize().unwrap();
278//!    ```
279//!
280//! 5. Profit! (This step is not automated by Ronky, sorry)
281//!
282//! ### Attribute Options
283//!
284//! - `#[arri(strict)]` - No extra properties allowed
285//! - `#[arri(transform = "snake_case")]` - Transform enum variant names
286//! - `#[arri(discriminator = "type")]` - Set discriminator field name
287//! - `#[arri(rename = "newName")]` - Rename a field or variant
288//! - `#[arri(nullable)]` - Mark a field as nullable
289//!
290//! ## ๐ŸŒŸ Final Thought
291//!
292//! Remember: Type conversion should be like a cat's nap โ€“ automatic, elegant, and requiring
293//! no effort on your part. Let Ronky handle the tedious work while you focus on building
294//! something amazing.
295//!
296//! Now go pet your cat (or dog, or rubber duck) โ€“ they've been waiting patiently while you
297//! read this documentation. โค๏ธ
298
299#[cfg(feature = "serialization")]
300mod serialization;
301
302#[cfg(feature = "derive")]
303extern crate ronky_derive;
304
305#[cfg(feature = "derive")]
306pub use ronky_derive::{Exported, Serializable as SerializableDerive};
307
308extern crate arri_repr;
309pub use arri_repr::*;
310
311#[cfg(feature = "serialization")]
312pub use serialization::{ExportedDeserialize, ExportedSerialize};
313
314pub static SCHEMA_VERSION: &str = "v0.0.8";
315
316// TODO: implement conversion from ATD to Rust types
317// | ATD Type | Rust Type |
318// |---|---|
319// | string | String |
320// | boolean | bool |
321// | timestamp | DateTime |
322// | float32 | f32 |
323// | float64 | f64 |
324// | int8 | i8 |
325// | uint8 | u8 |
326// | int16 | i16 |
327// | uint16 | u16 |
328// | int32 | i32 |
329// | uint32 | u32 |
330// | int64 | i64 |
331// | uint64 | u64 |