git-ents.gitmain
⌘K
foforge
read.rs67 lines · 2.3 KB · rusthistorycomment on this file
1//! The read half of the `RefStore` seam.
2//!
3//! `arch.refstore-read-cas-split` requires that a consumer able to check
4//! ref state never automatically gains the ability to change it. The gate
5//! (`gate.adoc`) is the reason this split exists: it is a pure function
6//! over ref-store reads and must be statically incapable of writing.
7
8use gix::refs::FullNameRef;
9use gix_hash::ObjectId;
10
11use crate::{RefIter, Result};
12
13/// The read half of a `RefStore`: everything needed to evaluate the gate
14/// (`gate.adoc`) or render a UI, with no path to mutation.
15///
16/// A type that also supports writes implements [`crate::RefStore`], which
17/// extends this trait with [`crate::RefStore::transaction`]. Code that only
18/// ever needs to read — the gate above all — should be written against
19/// `RefStoreRead` (or `&dyn RefStoreRead`) so it is impossible, not just
20/// disciplined, for it to write.
21///
22/// # Examples
23///
24/// ```
25/// use gix_ref_store::{LooseRefStore, RefStoreRead};
26///
27/// # fn open(dir: &std::path::Path) -> gix_ref_store::Result<()> {
28/// let store = LooseRefStore::open(dir)?;
29/// let read: &dyn RefStoreRead = &store;
30/// let name: gix::refs::FullName = "refs/heads/does-not-exist".try_into().expect("valid refname");
31/// assert_eq!(read.get(name.as_ref())?, None);
32/// # Ok(())
33/// # }
34/// ```
35// @relation(arch.refstore-read-cas-split, scope=file)
36pub trait RefStoreRead: Send + Sync {
37 /// The object id `name` currently points at, or `None` if `name` does
38 /// not exist.
39 fn get(&self, name: &FullNameRef) -> Result<Option<ObjectId>>;
40
41 /// Every ref under `prefix` (for example `refs/meta/`), with its
42 /// current tip.
43 fn iter_prefix(&self, prefix: &str) -> Result<RefIter>;
44}
45
46/// Blanket impl so a `RefStoreRead` behind any indirection remains usable
47/// as `RefStoreRead` itself — `&T`, `Box<T>`, and `std::sync::Arc<T>` all
48/// forward transparently.
49impl<T: RefStoreRead + ?Sized> RefStoreRead for &T {
50 fn get(&self, name: &FullNameRef) -> Result<Option<ObjectId>> {
51 (**self).get(name)
52 }
53
54 fn iter_prefix(&self, prefix: &str) -> Result<RefIter> {
55 (**self).iter_prefix(prefix)
56 }
57}
58
59impl<T: RefStoreRead + ?Sized> RefStoreRead for std::sync::Arc<T> {
60 fn get(&self, name: &FullNameRef) -> Result<Option<ObjectId>> {
61 (**self).get(name)
62 }
63
64 fn iter_prefix(&self, prefix: &str) -> Result<RefIter> {
65 (**self).iter_prefix(prefix)
66 }
67}