void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenBoundsCheck(std::ostream&, Size, Size, std::string) const override{};
// Body fields can only be dynamically sized.
const SizeField* size_field_{nullptr};
};
s << GetName() << ": " << param_type;
return true;
}
+
+void PacketField::GenBoundsCheck(std::ostream& s, Size start_offset, Size, std::string context) const {
+ Size size = GetSize();
+ s << "if bytes.len() < " << start_offset.bytes() + size.bytes() << " {";
+ s << " return Err(Error::InvalidLengthError{";
+ s << " obj: \"" << context << "\".to_string(),";
+ s << " field: \"" << GetName() << "\".to_string(),";
+ s << " wanted: " << start_offset.bytes() + size.bytes() << ",";
+ s << " got: bytes.len()});";
+ s << "}";
+}
virtual void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const = 0;
+ virtual void GenBoundsCheck(std::ostream& s, Size start_offset, Size, std::string) const;
+
virtual bool GetterIsByRef() const {
return true;
}
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenBoundsCheck(std::ostream&, Size, Size, std::string) const override{};
+
private:
Size size_;
};
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenBoundsCheck(std::ostream&, Size, Size, std::string) const override{};
+
// Payload fields can only be dynamically sized.
const SizeField* size_field_;
// Only used if the size of the payload is based on another field.
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenBoundsCheck(std::ostream&, Size, Size, std::string) const override{};
+
private:
std::string name_;
int size_;
return GetDataType();
}
+void StructField::GenBoundsCheck(std::ostream&, Size, Size, std::string) const {
+ // implicitly checked by the struct parser
+}
+
void StructField::GenRustGetter(std::ostream& s, Size start_offset, Size) const {
s << "let " << GetName() << " = ";
s << GetRustDataType() << "::parse(&bytes[" << start_offset.bytes() << "..";
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenBoundsCheck(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
+
private:
std::string type_name_;
return "Vec::<" + element_field_->GetRustDataType() + ">";
}
+void VectorField::GenBoundsCheck(std::ostream& s, Size start_offset, Size, std::string context) const {
+ auto element_field_type = GetElementField()->GetFieldType();
+ auto element_field = GetElementField();
+ auto element_size = element_field->GetSize().bytes();
+
+ if (element_field_type == ScalarField::kFieldType) {
+ if (size_field_ == nullptr) {
+ s << "let rem_ = (bytes.len() - " << start_offset.bytes() << ") % " << element_size << ";";
+ s << "if rem_ != 0 {";
+ s << " return Err(Error::InvalidLengthError{";
+ s << " obj: \"" << context << "\".to_string(),";
+ s << " field: \"" << GetName() << "\".to_string(),";
+ s << " wanted: bytes.len() + rem_,";
+ s << " got: bytes.len()});";
+ s << "}";
+ } else if (size_field_->GetFieldType() == CountField::kFieldType) {
+ s << "let want_ = " << start_offset.bytes() << " + ((" << size_field_->GetName() << " as usize) * "
+ << element_size << ");";
+ s << "if bytes.len() < want_ {";
+ s << " return Err(Error::InvalidLengthError{";
+ s << " obj: \"" << context << "\".to_string(),";
+ s << " field: \"" << GetName() << "\".to_string(),";
+ s << " wanted: want_,";
+ s << " got: bytes.len()});";
+ s << "}";
+ } else {
+ s << "let want_ = " << start_offset.bytes() << " + (" << size_field_->GetName() << " as usize)";
+ if (GetSizeModifier() != "") {
+ s << " - ((" << GetSizeModifier().substr(1) << ") / 8)";
+ }
+ s << ";";
+ s << "if bytes.len() < want_ {";
+ s << " return Err(Error::InvalidLengthError{";
+ s << " obj: \"" << context << "\".to_string(),";
+ s << " field: \"" << GetName() << "\".to_string(),";
+ s << " wanted: want_,";
+ s << " got: bytes.len()});";
+ s << "}";
+ if (GetSizeModifier() != "") {
+ s << "if ((" << size_field_->GetName() << " as usize) < ((" << GetSizeModifier().substr(1) << ") / 8)) {";
+ s << " return Err(Error::ImpossibleStructError);";
+ s << "}";
+ }
+ }
+ }
+}
+
void VectorField::GenRustGetter(std::ostream& s, Size start_offset, Size) const {
auto element_field_type = GetElementField()->GetFieldType();
auto element_field = GetElementField();
s << "];";
s << "while parsable_.len() > 0 {";
}
- s << " let parsed = " << element_field->GetRustDataType() << "::parse(&parsable_)?;";
- s << " parsable_ = &parsable_[parsed.get_total_size()..];";
+ s << " match " << element_field->GetRustDataType() << "::parse(&parsable_) {";
+ s << " Ok(parsed) => {";
+ s << " parsable_ = &parsable_[parsed.get_total_size()..];";
s << GetName() << ".push(parsed);";
+ s << " },";
+ s << " Err(Error::ImpossibleStructError) => break,";
+ s << " Err(e) => return Err(e),";
+ s << " }";
s << "}";
}
}
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenBoundsCheck(std::ostream& s, Size start_offset, Size end_offset, std::string context) const override;
+
const std::string name_;
const PacketField* element_field_{nullptr};
field: String,
value: u64,
},
+ #[error("when parsing {obj}.{field} needed length of {wanted} but got {got}")]
+ InvalidLengthError {
+ obj: String,
+ field: String,
+ wanted: usize,
+ got: usize,
+ },
+ #[error("Due to size restrictions a struct could not be parsed.")]
+ ImpossibleStructError,
}
pub trait Packet {
<< "no method exists to determine field location from begin() or end().\n";
}
+ field->GenBoundsCheck(s, start_field_offset, end_field_offset, name_);
field->GenRustGetter(s, start_field_offset, end_field_offset);
}
<< "no method exists to determine field location from begin() or end().\n";
}
+ field->GenBoundsCheck(s, start_field_offset, end_field_offset, name_);
field->GenRustGetter(s, start_field_offset, end_field_offset);
}