diff --git a/worker-sys/src/types/r2/range.rs b/worker-sys/src/types/r2/range.rs index 7ec2dfc1..8115c5e3 100644 --- a/worker-sys/src/types/r2/range.rs +++ b/worker-sys/src/types/r2/range.rs @@ -3,7 +3,7 @@ use wasm_bindgen::prelude::*; #[wasm_bindgen] #[derive(Debug, Clone)] pub struct R2Range { - pub offset: Option, - pub length: Option, - pub suffix: Option, + pub offset: Option, + pub length: Option, + pub suffix: Option, } diff --git a/worker/src/r2/builder.rs b/worker/src/r2/builder.rs index d1fab00b..df8bce32 100644 --- a/worker/src/r2/builder.rs +++ b/worker/src/r2/builder.rs @@ -93,34 +93,48 @@ impl From for JsObject { #[derive(Debug, Clone, PartialEq, Eq)] pub enum Range { - OffsetWithLength { offset: u32, length: u32 }, - OffsetWithOptionalLength { offset: u32, length: Option }, - OptionalOffsetWithLength { offset: Option, length: u32 }, - Suffix { suffix: u32 }, + /// Read `length` bytes starting at `offset`. + OffsetWithLength { offset: u64, length: u64 }, + /// Read from `offset` to the end of the object. + OffsetToEnd { offset: u64 }, + /// Read `length` bytes starting at the beginning of the object. + Prefix { length: u64 }, + /// Read `suffix` bytes from the end of the object. + Suffix { suffix: u64 }, +} + +const MAX_SAFE_INTEGER: u64 = js_sys::Number::MAX_SAFE_INTEGER as u64; + +fn check_range_precision(value: u64) -> f64 { + assert!( + value <= MAX_SAFE_INTEGER, + "Integer precision loss when converting to JavaScript number" + ); + value as f64 } impl From for JsObject { fn from(val: Range) -> Self { match val { Range::OffsetWithLength { offset, length } => js_object! { - "offset" => Some(offset), - "length" => Some(length), + "offset" => Some(check_range_precision(offset)), + "length" => Some(check_range_precision(length)), "suffix" => JsValue::UNDEFINED, }, - Range::OffsetWithOptionalLength { offset, length } => js_object! { - "offset" => Some(offset), - "length" => length, + Range::OffsetToEnd { offset } => js_object! { + "offset" => Some(check_range_precision(offset)), + "length" => JsValue::UNDEFINED, "suffix" => JsValue::UNDEFINED, }, - Range::OptionalOffsetWithLength { offset, length } => js_object! { - "offset" => offset, - "length" => Some(length), + Range::Prefix { length } => js_object! { + "offset" => JsValue::UNDEFINED, + "length" => Some(check_range_precision(length)), "suffix" => JsValue::UNDEFINED, }, Range::Suffix { suffix } => js_object! { "offset" => JsValue::UNDEFINED, "length" => JsValue::UNDEFINED, - "suffix" => Some(suffix), + "suffix" => Some(check_range_precision(suffix)), }, } } @@ -131,16 +145,19 @@ impl TryFrom for Range { fn try_from(val: R2RangeSys) -> Result { Ok(match (val.offset, val.length, val.suffix) { - (Some(offset), Some(length), None) => Self::OffsetWithLength { offset, length }, - (Some(offset), None, None) => Self::OffsetWithOptionalLength { - offset, - length: None, + (Some(offset), Some(length), None) => Self::OffsetWithLength { + offset: offset.round() as u64, + length: length.round() as u64, + }, + (Some(offset), None, None) => Self::OffsetToEnd { + offset: offset.round() as u64, + }, + (None, Some(length), None) => Self::Prefix { + length: length.round() as u64, }, - (None, Some(length), None) => Self::OptionalOffsetWithLength { - offset: None, - length, + (None, None, Some(suffix)) => Self::Suffix { + suffix: suffix.round() as u64, }, - (None, None, Some(suffix)) => Self::Suffix { suffix }, _ => return Err(Error::JsError("invalid range".into())), }) }