Scans

Struct Scans 

Source
pub struct Scans {
    pub metadata_end: Option<usize>,
    pub frame_render_start: Option<usize>,
    pub first_scan_end: Option<usize>,
    pub good_scan_end: Option<usize>,
    pub file_size: usize,
}
Expand description

Key positions in a progressive image file

cloudflare_soos::Scans::from_file(&input_file)?.cf_priority_change_headers()?;

Fields§

§metadata_end: Option<usize>

Byte position where metadata ends. This many bytes are preceeding start of pixel data. It’s usually <200 bytes, unless the image has color profiles or other bloat.

§frame_render_start: Option<usize>

All metadata + minimum amount of data to make browsers render anything (in case they don’t reserve space based on metadata)

§first_scan_end: Option<usize>

Byte position where the first (lowest-quality) progressive scan ends. This many bytes are needed to display anything on screen. It’s usually 12-15% of the file size.

§good_scan_end: Option<usize>

Byte position where most of ok-quality pixel data ends. This many bytes are needed to display a good-enough image. It’s usually about 50% of the file size.

§file_size: usize

Size of the whole image file, in bytes. The size is only used for heuristics, so the value may be approximate, but it must be greater than all other positions set in this struct.

Implementations§

Source§

impl Scans

Source

pub fn from_file(input_file: &[u8]) -> Result<Self>

Analyze an image file to find byte ranges of its metadata and progressive scans

Examples found in repository?
examples/rfc9218-priority.rs (line 16)
11fn main() {
12    let mut args = env::args().skip(1);
13    let input_path = args.next().unwrap_or_else(|| usage());
14    let input_file = fs::read(input_path).expect("The specified input file could not be opened");
15
16    let scans = soos::Scans::from_file(&input_file).expect("Scan failed");
17
18    println!("{scans:#?}");
19    println!("priority: {}", scans.rfc9218_priority_change_headers().unwrap());
20}
More examples
Hide additional examples
examples/cf-priority.rs (line 16)
11fn main() {
12    let mut args = env::args().skip(1);
13    let input_path = args.next().unwrap_or_else(|| usage());
14    let input_file = fs::read(input_path).expect("The specified input file could not be opened");
15
16    let scans = soos::Scans::from_file(&input_file).expect("Scan failed");
17
18    println!("{scans:#?}");
19    let (pri, pri_change) = scans.cf_priority_change_headers().unwrap();
20    println!("cf-priority: {pri}");
21    println!("cf-priority-change: {pri_change}");
22}
examples/chop.rs (line 18)
13fn main() {
14    let mut args = env::args_os().skip(1);
15    let input_path = PathBuf::from(args.next().unwrap_or_else(|| usage()));
16    let input_file = fs::read(&input_path).expect("The specified input file could not be opened");
17
18    let scans = soos::Scans::from_file(&input_file).expect("Scan failed");
19
20    println!("{scans:#?}");
21
22    write_up_to(&input_path, &input_file, "0-meta", scans.metadata_end);
23    write_up_to(
24        &input_path,
25        &input_file,
26        "1-render",
27        scans.frame_render_start,
28    );
29    write_up_to(
30        &input_path,
31        &input_file,
32        "2-first_scan",
33        scans.first_scan_end,
34    );
35    write_up_to(&input_path, &input_file, "3-good_scan", scans.good_scan_end);
36}
Source

pub fn cf_priority_change_headers(&self) -> Result<(String, String)>

Assumes the HTTP2 priorities are:

  • 50 = critical js/css, fonts + image metadata
  • 30 = regular js/css, followed by other images + JPEG DC
  • 20 = low-priority image bodies
  • 10 = idle

Returns cf-priority and cf-priority-change header values, respectively.

Examples found in repository?
examples/cf-priority.rs (line 19)
11fn main() {
12    let mut args = env::args().skip(1);
13    let input_path = args.next().unwrap_or_else(|| usage());
14    let input_file = fs::read(input_path).expect("The specified input file could not be opened");
15
16    let scans = soos::Scans::from_file(&input_file).expect("Scan failed");
17
18    println!("{scans:#?}");
19    let (pri, pri_change) = scans.cf_priority_change_headers().unwrap();
20    println!("cf-priority: {pri}");
21    println!("cf-priority-change: {pri_change}");
22}
Source

pub fn rfc9218_priority_change_headers(&self) -> Result<String>

Examples found in repository?
examples/rfc9218-priority.rs (line 19)
11fn main() {
12    let mut args = env::args().skip(1);
13    let input_path = args.next().unwrap_or_else(|| usage());
14    let input_file = fs::read(input_path).expect("The specified input file could not be opened");
15
16    let scans = soos::Scans::from_file(&input_file).expect("Scan failed");
17
18    println!("{scans:#?}");
19    println!("priority: {}", scans.rfc9218_priority_change_headers().unwrap());
20}

Trait Implementations§

Source§

impl Clone for Scans

Source§

fn clone(&self) -> Scans

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Scans

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Scans

Source§

fn default() -> Scans

Returns the “default value” for a type. Read more
Source§

impl PartialEq for Scans

Source§

fn eq(&self, other: &Scans) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl StructuralPartialEq for Scans

Auto Trait Implementations§

§

impl Freeze for Scans

§

impl RefUnwindSafe for Scans

§

impl Send for Scans

§

impl Sync for Scans

§

impl Unpin for Scans

§

impl UnwindSafe for Scans

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.