1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! Experimental storing and querying of zones and zone trees.
//!
//! # Zone trees
//!
//! A [`ZoneTree`] is a multi-rooted hierarchy of [`Zone`]s, each root being
//! the apex of a subtree for a distinct [`Class`]. `Zone`s can be inserted
//! and removed from the tree, looked up by containing or exact name, and the
//! set of zones in the tree can be iterated over.
//!
//! # Zones
//!
//! The `Zone`s that a tree is comprised of can be created by feeding
//! zonefiles or individual resource records into [`ZoneBuilder`] and then
//! inserted into a `ZoneTree`. `Zone`s can also be used directly without
//! inserting them into a `ZoneTree`.
//!
//! `Zone`s can be queried via their [read interface][traits::ReadableZone] by
//! [`Class`], [`Rtype`] and [`Name`] to produce an [`Answer`], which in turn
//! can be used to produce a response [`Message`] for serving to a DNS client.
//! Entire `Zone`s can also be [`walk`]ed to inspect or export their content.
//!
//! Updating a zone can be done via the low-level [`WritableZone`] interface
//! or using a higher-level helper like the [`ZoneUpdater`]. Updates to a
//! `Zone` can be captured as difference sets which for example can be used to
//! respond to IXFR queries.
//!
//! # Backing stores
//!
//! By default `Zone`s are stored in memory only. Zones with other types of
//! backing store can be created by implementing the [`ZoneStore`] trait and
//! passing an instance of the implementing struct to [`Zone::new`]. Zones
//! with different backing store types can be mixed and matched within the
//! same tree. Backing stores can be synchronous or asynchronous, the latter
//! being useful for a remote backing store such as a distributed database.
//!
//! The default in-memory zone implementation uses an append only write
//! strategy with new zone versions only becoming visible to consumers on
//! commit and existing zone versions remaining readable during write
//! operations.
//!
//! # Usage
//!
//! The example below shows how to populate a [`ZoneTree`] from a zonefile.
//! For more examples of using [`Zone`]s and [`ZoneTree`]s including
//! implementing an alternate zone backing store for your [`Zone`]s, see the
//! [examples in the GitHub
//! repository](https://github.com/NLnetLabs/domain/tree/main/examples).
//!
//! The following example builds and queries a [`ZoneTree`] containing a
//! single in-memory [`Zone`].
//!
//! ```
//! use domain::base::iana::{Class, Rcode, Rtype};
//! use domain::base::name::Name;
//! use domain::zonefile::inplace;
//! use domain::zonetree::parsed;
//! use domain::zonetree::{Answer, Zone, ZoneBuilder, ZoneTree};
//!
//! // Prepare some zone file bytes to demonstrate with.
//! let zone_file = include_bytes!("../../test-data/zonefiles/nsd-example.txt");
//! let mut zone_bytes = std::io::BufReader::new(&zone_file[..]);
//!
//! // Read, parse and build a zone.
//! let reader = inplace::Zonefile::load(&mut zone_bytes).unwrap();
//! let parsed = parsed::Zonefile::try_from(reader).unwrap();
//! let builder = ZoneBuilder::try_from(parsed).unwrap();
//!
//! // Turn the builder into a zone.
//! let zone = Zone::from(builder);
//!
//! // Equivalent but shorter:
//! let mut zone_bytes = std::io::BufReader::new(&zone_file[..]);
//! let reader = inplace::Zonefile::load(&mut zone_bytes).unwrap();
//! let zone = Zone::try_from(reader).unwrap();
//!
//! // Insert the zone into a zone tree.
//! let mut tree = ZoneTree::new();
//! tree.insert_zone(zone).unwrap();
//!
//! // Query the zone tree.
//! let qname = Name::bytes_from_str("example.com").unwrap();
//! let qtype = Rtype::A;
//! let found_zone = tree.find_zone(&qname, Class::IN).unwrap();
//! let res: Answer = found_zone.read().query(qname, qtype).unwrap();
//!
//! // Verify that we found a result.
//! assert_eq!(res.rcode(), Rcode::NOERROR);
//! ```
//!
//! [`query`]: ReadableZone::query
//! [`walk`]: ReadableZone::walk
//! [`Class`]: crate::base::iana::Class
//! [`Rtype`]: crate::base::iana::Rtype
//! [`Name`]: crate::base::name::Name
//! [`Message`]: crate::base::Message
//! [`NoError`]: crate::base::iana::code::Rcode::NOERROR
//! [`NxDomain`]: crate::base::iana::code::Rcode::NXDOMAIN
//! [`ZoneBuilder`]: in_memory::ZoneBuilder
//! [`ZoneUpdater`]: update::ZoneUpdater
pub use ;
pub use ZoneBuilder;
pub use ;
pub use ;
pub use ;
pub use WalkOp;
pub use Zone;
/// Zone related utilities.