Skip to content

Commit ac5ee86

Browse files
authored
Merge pull request #3 from woshilapin/doc
[doc] Move the documentation in the main file
2 parents cc2d097 + dc71910 commit ac5ee86

File tree

2 files changed

+140
-142
lines changed

2 files changed

+140
-142
lines changed

src/lib.rs

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,146 @@
33
//! By default, feature `relations_procmacro` is enabled, exposing macros to
44
//! help build relations. See documentation of the crate `relations_procmacro`
55
//! for more information.
6+
//!
7+
//! This module defines types for modeling the relations between
8+
//! objects, and use them thanks to the `GetCorresponding` custom
9+
//! derive.
10+
//!
11+
//! Let's clarify that with an example. Suppose that `Bike`s have a
12+
//! `Brand`. `Bike`s also have an `Owner`, and these `Owner`s have a
13+
//! `Job`. `Bike`s also have a `Kind`.
14+
//!
15+
//! ```raw
16+
//! Brand - Bike - Owner - Job
17+
//! |
18+
//! Kind
19+
//! ```
20+
//!
21+
//! Let's defines these relations and use them a bit:
22+
//!
23+
//! ```no_run
24+
//! # use relations_procmacro::*;
25+
//! # use relations::*;
26+
//! # use typed_index_collection::Idx;
27+
//! # struct Bike;
28+
//! # struct Brand;
29+
//! # struct Owner;
30+
//! # struct Job;
31+
//! # struct Kind;
32+
//! # fn get_mbk_brand() -> Idx<Brand> { unimplemented!() }
33+
//! #[derive(Default, GetCorresponding)]
34+
//! pub struct World {
35+
//! brands_to_bikes: OneToMany<Brand, Bike>,
36+
//! owners_to_bikes: OneToMany<Owner, Bike>,
37+
//! jobs_to_owners: OneToMany<Job, Owner>,
38+
//! kinds_to_bikes: OneToMany<Kind, Bike>,
39+
//! }
40+
//! let world = World::default();
41+
//! let mbk: Idx<Brand> = get_mbk_brand();
42+
//! let owners_with_mbk: IdxSet<Owner> = world.get_corresponding_from_idx(mbk);
43+
//! let jobs_with_mbk: IdxSet<Job> = world.get_corresponding(&owners_with_mbk);
44+
//! println!(
45+
//! "{} owners with {} different jobs own a bike of the brand MBK.",
46+
//! owners_with_mbk.len(),
47+
//! jobs_with_mbk.len()
48+
//! );
49+
//! ```
50+
//!
51+
//! First, we want to model the relations between the object. One bike
52+
//! has a brand, and a brand has several bikes (hopefully). Thus, we
53+
//! use a `OneToMany<Bike, Brand>` to model this relation.
54+
//!
55+
//! We repeat this process to model every relation. We obtain without
56+
//! too much effort the `World` struct.
57+
//!
58+
//! The `GetCorresponding` derive looks at each field of the `World`
59+
//! struct, keeping the fields containing `_to_` with a type with 2
60+
//! generics, and interpret that as a relation. For example,
61+
//! `bikes_to_brands: OneToMany<Bike, Brand>` is a relation between
62+
//! `Bike` and `Brand`. Using all the relations, it generates a graph,
63+
//! compute the shortest path between all the types, and generate an
64+
//! `impl GetCorresponding` for each feasible path.
65+
//!
66+
//! These `impl GetCorresponding` are used by
67+
//! `World::get_corresponding_from_idx` and `World::get_corresponding`
68+
//! that are helpers to explore the `World`.
69+
//!
70+
//! Thus, when we call `world.get_corresponding_from_idx(mbk)` for
71+
//! `Owner`, we will use the generated code that, basically, gets all
72+
//! the `Bike`s corresponding to the `Brand` MBK, and then gets all
73+
//! the `Owner`s corresponding to these `Bike`s.
74+
//!
75+
//! Imagine that, in our application, we use a lot the `Owner->Kind`
76+
//! and `Brand->Kind` search. To do these searches, we pass by
77+
//! `Bike`, and there is a lot of `Bike`s in our model. Thus, as an
78+
//! optimization, we want to precompute these relations.
79+
//!
80+
//! ```raw
81+
//! Brand - Bike - Owner - Job
82+
//! \ | /
83+
//! `-- Kind --'
84+
//! ```
85+
//!
86+
//! The shortcuts `Brand - Kind` and `Kind - Owner` allow our
87+
//! optimization, but we now have a problem for the `Owner->Brand`
88+
//! search: we can do `Owner->Kind->Brand` and `Owner->Bike->Brand`
89+
//! with a cost of 2. The first solution is clearly wrong, introduced
90+
//! by our shortcuts. To fix this problem, we can put a weight of 1.9
91+
//! on `Brand - Kind` and `Kind - Owner`. The path
92+
//! `Owner->Kind->Brand` now cost 3.8 and is discarded.
93+
//!
94+
//! Let's implement that:
95+
//!
96+
//! ```
97+
//! # use relations_procmacro::*;
98+
//! # use relations::*;
99+
//! # use typed_index_collection::Idx;
100+
//! # struct Bike;
101+
//! # struct Brand;
102+
//! # struct Owner;
103+
//! # struct Job;
104+
//! # struct Kind;
105+
//! # fn get_mbk_brand() -> Idx<Brand> { unimplemented!() }
106+
//! #[derive(GetCorresponding)]
107+
//! pub struct World {
108+
//! brands_to_bikes: OneToMany<Brand, Bike>,
109+
//! owners_to_bikes: OneToMany<Owner, Bike>,
110+
//! jobs_to_owners: OneToMany<Job, Owner>,
111+
//! kinds_to_bikes: OneToMany<Kind, Bike>,
112+
//!
113+
//! // shortcuts
114+
//! #[get_corresponding(weight = "1.9")]
115+
//! brands_to_kinds: ManyToMany<Brand, Kind>,
116+
//! #[get_corresponding(weight = "1.9")]
117+
//! kinds_to_owners: ManyToMany<Kind, Owner>,
118+
//! }
119+
//! # fn create_brands_to_bikes() -> OneToMany<Brand, Bike> { unimplemented!() }
120+
//! # fn create_owners_to_bikes() -> OneToMany<Owner, Bike> { unimplemented!() }
121+
//! # fn create_jobs_to_owners() -> OneToMany<Job, Owner> { unimplemented!() }
122+
//! # fn create_kinds_to_bikes() -> OneToMany<Kind, Bike> { unimplemented!() }
123+
//! impl World {
124+
//! fn new() -> World {
125+
//! let brands_to_bikes = create_brands_to_bikes();
126+
//! let owners_to_bikes = create_owners_to_bikes();
127+
//! let jobs_to_owners = create_jobs_to_owners();
128+
//! let kinds_to_bikes = create_kinds_to_bikes();
129+
//! World {
130+
//! brands_to_kinds: ManyToMany::from_relations_sink(
131+
//! &brands_to_bikes,
132+
//! &kinds_to_bikes,
133+
//! ),
134+
//! kinds_to_owners: ManyToMany::from_relations_sink(
135+
//! &kinds_to_bikes,
136+
//! &owners_to_bikes,
137+
//! ),
138+
//! brands_to_bikes,
139+
//! owners_to_bikes,
140+
//! jobs_to_owners,
141+
//! kinds_to_bikes,
142+
//! }
143+
//! }
144+
//! }
145+
//! ```
6146
7147
mod error;
8148
mod relations;

src/relations.rs

Lines changed: 0 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,145 +1,3 @@
1-
//! Modeling the relations between objects.
2-
//!
3-
//! This module defines types for modeling the relations between
4-
//! objects, and use them thanks to the `GetCorresponding` custom
5-
//! derive.
6-
//!
7-
//! Let's clarify that with an example. Suppose that `Bike`s have a
8-
//! `Brand`. `Bike`s also have an `Owner`, and these `Owner`s have a
9-
//! `Job`. `Bike`s also have a `Kind`.
10-
//!
11-
//! ```raw
12-
//! Brand - Bike - Owner - Job
13-
//! |
14-
//! Kind
15-
//! ```
16-
//!
17-
//! Let's defines these relations and use them a bit:
18-
//!
19-
//! ```no_run
20-
//! # use relations_procmacro::*;
21-
//! # use relations::*;
22-
//! # use typed_index_collection::Idx;
23-
//! # struct Bike;
24-
//! # struct Brand;
25-
//! # struct Owner;
26-
//! # struct Job;
27-
//! # struct Kind;
28-
//! # fn get_mbk_brand() -> Idx<Brand> { unimplemented!() }
29-
//! #[derive(Default, GetCorresponding)]
30-
//! pub struct World {
31-
//! brands_to_bikes: OneToMany<Brand, Bike>,
32-
//! owners_to_bikes: OneToMany<Owner, Bike>,
33-
//! jobs_to_owners: OneToMany<Job, Owner>,
34-
//! kinds_to_bikes: OneToMany<Kind, Bike>,
35-
//! }
36-
//! let world = World::default();
37-
//! let mbk: Idx<Brand> = get_mbk_brand();
38-
//! let owners_with_mbk: IdxSet<Owner> = world.get_corresponding_from_idx(mbk);
39-
//! let jobs_with_mbk: IdxSet<Job> = world.get_corresponding(&owners_with_mbk);
40-
//! println!(
41-
//! "{} owners with {} different jobs own a bike of the brand MBK.",
42-
//! owners_with_mbk.len(),
43-
//! jobs_with_mbk.len()
44-
//! );
45-
//! ```
46-
//!
47-
//! First, we want to model the relations between the object. One bike
48-
//! has a brand, and a brand has several bikes (hopefully). Thus, we
49-
//! use a `OneToMany<Bike, Brand>` to model this relation.
50-
//!
51-
//! We repeat this process to model every relation. We obtain without
52-
//! too much effort the `World` struct.
53-
//!
54-
//! The `GetCorresponding` derive looks at each field of the `World`
55-
//! struct, keeping the fields containing `_to_` with a type with 2
56-
//! generics, and interpret that as a relation. For example,
57-
//! `bikes_to_brands: OneToMany<Bike, Brand>` is a relation between
58-
//! `Bike` and `Brand`. Using all the relations, it generates a graph,
59-
//! compute the shortest path between all the types, and generate an
60-
//! `impl GetCorresponding` for each feasible path.
61-
//!
62-
//! These `impl GetCorresponding` are used by
63-
//! `World::get_corresponding_from_idx` and `World::get_corresponding`
64-
//! that are helpers to explore the `World`.
65-
//!
66-
//! Thus, when we call `world.get_corresponding_from_idx(mbk)` for
67-
//! `Owner`, we will use the generated code that, basically, gets all
68-
//! the `Bike`s corresponding to the `Brand` MBK, and then gets all
69-
//! the `Owner`s corresponding to these `Bike`s.
70-
//!
71-
//! Imagine that, in our application, we use a lot the `Owner->Kind`
72-
//! and `Brand->Kind` search. To do these searches, we pass by
73-
//! `Bike`, and there is a lot of `Bike`s in our model. Thus, as an
74-
//! optimization, we want to precompute these relations.
75-
//!
76-
//! ```raw
77-
//! Brand - Bike - Owner - Job
78-
//! \ | /
79-
//! `-- Kind --'
80-
//! ```
81-
//!
82-
//! The shortcuts `Brand - Kind` and `Kind - Owner` allow our
83-
//! optimization, but we now have a problem for the `Owner->Brand`
84-
//! search: we can do `Owner->Kind->Brand` and `Owner->Bike->Brand`
85-
//! with a cost of 2. The first solution is clearly wrong, introduced
86-
//! by our shortcuts. To fix this problem, we can put a weight of 1.9
87-
//! on `Brand - Kind` and `Kind - Owner`. The path
88-
//! `Owner->Kind->Brand` now cost 3.8 and is discarded.
89-
//!
90-
//! Let's implement that:
91-
//!
92-
//! ```
93-
//! # use relations_procmacro::*;
94-
//! # use relations::*;
95-
//! # use typed_index_collection::Idx;
96-
//! # struct Bike;
97-
//! # struct Brand;
98-
//! # struct Owner;
99-
//! # struct Job;
100-
//! # struct Kind;
101-
//! # fn get_mbk_brand() -> Idx<Brand> { unimplemented!() }
102-
//! #[derive(GetCorresponding)]
103-
//! pub struct World {
104-
//! brands_to_bikes: OneToMany<Brand, Bike>,
105-
//! owners_to_bikes: OneToMany<Owner, Bike>,
106-
//! jobs_to_owners: OneToMany<Job, Owner>,
107-
//! kinds_to_bikes: OneToMany<Kind, Bike>,
108-
//!
109-
//! // shortcuts
110-
//! #[get_corresponding(weight = "1.9")]
111-
//! brands_to_kinds: ManyToMany<Brand, Kind>,
112-
//! #[get_corresponding(weight = "1.9")]
113-
//! kinds_to_owners: ManyToMany<Kind, Owner>,
114-
//! }
115-
//! # fn create_brands_to_bikes() -> OneToMany<Brand, Bike> { unimplemented!() }
116-
//! # fn create_owners_to_bikes() -> OneToMany<Owner, Bike> { unimplemented!() }
117-
//! # fn create_jobs_to_owners() -> OneToMany<Job, Owner> { unimplemented!() }
118-
//! # fn create_kinds_to_bikes() -> OneToMany<Kind, Bike> { unimplemented!() }
119-
//! impl World {
120-
//! fn new() -> World {
121-
//! let brands_to_bikes = create_brands_to_bikes();
122-
//! let owners_to_bikes = create_owners_to_bikes();
123-
//! let jobs_to_owners = create_jobs_to_owners();
124-
//! let kinds_to_bikes = create_kinds_to_bikes();
125-
//! World {
126-
//! brands_to_kinds: ManyToMany::from_relations_sink(
127-
//! &brands_to_bikes,
128-
//! &kinds_to_bikes,
129-
//! ),
130-
//! kinds_to_owners: ManyToMany::from_relations_sink(
131-
//! &kinds_to_bikes,
132-
//! &owners_to_bikes,
133-
//! ),
134-
//! brands_to_bikes,
135-
//! owners_to_bikes,
136-
//! jobs_to_owners,
137-
//! kinds_to_bikes,
138-
//! }
139-
//! }
140-
//! }
141-
//! ```
142-
1431
use crate::Error;
1442
use derivative::Derivative;
1453
use std::collections::{BTreeMap, BTreeSet};

0 commit comments

Comments
 (0)