imago/
lib.rs

1// #![feature(async_drop)] -- enable with async-drop
2#![cfg_attr(all(doc, nightly), feature(doc_auto_cfg))] // expect nightly for doc
3#![warn(missing_docs)]
4#![warn(clippy::missing_docs_in_private_items)]
5
6//! Provides access to VM image formats.
7//!
8//! Simple example (requires the `sync-wrappers` feature):
9//! ```no_run
10//! # #[cfg(feature = "sync-wrappers")]
11//! # || -> std::io::Result<()> {
12//! use imago::file::File;
13//! use imago::qcow2::Qcow2;
14//! use imago::{FormatDriverBuilder, PermissiveImplicitOpenGate, SyncFormatAccess};
15//! use std::fs::OpenOptions;
16//!
17//! // Produce read-only qcow2 instance using purely `File` for storage
18//! let mut qcow2 = Qcow2::<File>::builder_path("image.qcow2")
19//!     .open_sync(PermissiveImplicitOpenGate::default())?;
20//!
21//! let qcow2 = SyncFormatAccess::new(qcow2)?;
22//!
23//! let mut buf = vec![0u8; 512];
24//! qcow2.read(&mut buf, 0)?;
25//! # Ok::<(), std::io::Error>(())
26//! # };
27//! ```
28//!
29//! Another example, using the native async interface instead of sync wrapper functions, explicitly
30//! overriding the implicit references contained in qcow2 files, and showcasing using different
31//! types of storage (specifically normal files and null storage):
32//! ```no_run
33//! # let _ = async {
34//! use imago::file::File;
35//! use imago::null::Null;
36//! use imago::qcow2::Qcow2;
37//! use imago::raw::Raw;
38//! use imago::{
39//!     DenyImplicitOpenGate, DynStorage, FormatAccess, FormatDriverBuilder,
40//!     PermissiveImplicitOpenGate, Storage, StorageOpenOptions,
41//! };
42//! use std::sync::Arc;
43//!
44//! // Produce qcow2 instance with arbitrary (and potentially mixed) storage instances
45//! // (By using `Box<dyn DynStorage>` as the `Storage` type.)
46//!
47//! let backing_storage: Box<dyn DynStorage> = Box::new(Null::new(0));
48//! let backing = Raw::builder(backing_storage)
49//!     .open(DenyImplicitOpenGate::default())
50//!     .await?;
51//! let backing = Arc::new(FormatAccess::new(backing));
52//!
53//! // `Box<dyn DynStorage>::open()` defaults to using the `imago::file::File` driver, so we can
54//! // use paths with `Box<dyn DynStorage>`, too.
55//! // Despite explicitly setting a backing image, we still need `PermissiveImplicitOpenGate`
56//! // instead of `DenyImplicitOpenGate`, because `builder_path()` will need to implicitly open
57//! // that storage object.  Passing an explicitly opened storage object via `builder()` would
58//! // remedy that.
59//! let qcow2 = Qcow2::builder_path("image.qcow2")
60//!     .storage_open_options(StorageOpenOptions::new().direct(true))
61//!     .write(true)
62//!     .backing(Some(Arc::clone(&backing)))
63//!     .open(PermissiveImplicitOpenGate::default())
64//!     .await?;
65//!
66//! let qcow2 = FormatAccess::new(qcow2);
67//!
68//! let mut buf = vec![0u8; 512];
69//! qcow2.read(&mut buf, 0).await?;
70//!
71//! qcow2.flush().await?;
72//! # Ok::<(), std::io::Error>(())
73//! # };
74//! ```
75//!
76//! # Flushing
77//!
78//! Given that `AsyncDrop` is not stable yet (and probably will not be stable for a long time),
79//! callers must ensure that images are properly flushed before dropping them, i.e. call
80//! `.flush().await` on any image that is not read-only.
81//!
82//! (The synchronous wrapper [`SyncFormatAccess`] does perform a synchronous flush in its `Drop`
83//! implementation.)
84//!
85//! # Features
86//!
87//! - `sync-wrappers`: Provide synchronous wrappers for the native `async` interface.  Note that
88//!   these build a `tokio` runtime in which they run the `async` functions, so using the `async`
89//!   interface is definitely preferred.
90//!
91//! - `vm-memory`: Provide conversion functions
92//!   [`IoVector::from_volatile_slice`](io_buffers::IoVector::from_volatile_slice) and
93//!   [`IoVectorMut::from_volatile_slice`](io_buffers::IoVectorMut::from_volatile_slice) to convert
94//!   the vm-memory crate’s `[VolatileSlice]` arrays into imago’s native I/O vectors.
95
96pub mod annotated;
97mod async_lru_cache;
98pub mod file;
99pub mod format;
100pub mod io_buffers;
101mod macros;
102mod misc_helpers;
103pub mod null;
104pub mod qcow2;
105pub mod raw;
106pub mod storage;
107mod vector_select;
108
109pub use format::access::{FormatAccess, Mapping};
110pub use format::builder::{FormatCreateBuilder, FormatDriverBuilder};
111pub use format::drivers::ShallowMapping;
112pub use format::gate::{DenyImplicitOpenGate, PermissiveImplicitOpenGate};
113#[cfg(feature = "sync-wrappers")]
114pub use format::sync_wrappers::SyncFormatAccess;
115pub use storage::ext::StorageExt;
116pub use storage::{DynStorage, Storage, StorageCreateOptions, StorageOpenOptions};