Skip to content

Commit 6172124

Browse files
committed
response/result.rs: Replace generate_deser_type macro with a function
This macro is unnecessary, function is enough here. For ease of future development, lets get rid of such macros.
1 parent 0e0b754 commit 6172124

File tree

1 file changed

+96
-91
lines changed

1 file changed

+96
-91
lines changed

scylla-cql/src/frame/response/result.rs

Lines changed: 96 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::cql_to_rust::{FromRow, FromRowError};
22
use crate::frame::frame_errors::{
33
ColumnSpecParseError, ColumnSpecParseErrorKind, CqlResultParseError, CqlTypeParseError,
4-
PreparedParseError, ResultMetadataParseError, RowsParseError, SchemaChangeEventParseError,
5-
SetKeyspaceParseError, TableSpecParseError,
4+
LowLevelDeserializationError, PreparedParseError, ResultMetadataParseError, RowsParseError,
5+
SchemaChangeEventParseError, SetKeyspaceParseError, TableSpecParseError,
66
};
77
use crate::frame::request::query::PagingStateResponse;
88
use crate::frame::response::event::SchemaChangeEvent;
@@ -603,99 +603,104 @@ pub enum Result {
603603
SchemaChange(SchemaChange),
604604
}
605605

606-
macro_rules! generate_deser_type {
607-
($deser_type: ident, $l: lifetime, $read_string: expr) => {
608-
fn $deser_type<'frame>(
609-
buf: &mut &'frame [u8],
610-
) -> StdResult<ColumnType<$l>, CqlTypeParseError> {
611-
use ColumnType::*;
612-
let id = types::read_short(buf)
613-
.map_err(|err| CqlTypeParseError::TypeIdParseError(err.into()))?;
614-
Ok(match id {
615-
0x0000 => {
616-
// We use types::read_string instead of $read_string here on purpose.
617-
// Chances are the underlying string is `...DurationType`, in which case
618-
// we don't need to allocate it at all. Only for Custom types
619-
// (which we don't support anyway) do we need to allocate.
620-
// OTOH, the macro argument function deserializes borrowed OR owned string;
621-
// here we want to always deserialize borrowed string.
622-
let type_str = types::read_string(buf)
623-
.map_err(CqlTypeParseError::CustomTypeNameParseError)?;
624-
match type_str {
625-
"org.apache.cassandra.db.marshal.DurationType" => Duration,
626-
_ => Custom(type_str.to_owned().into()),
627-
}
628-
}
629-
0x0001 => Ascii,
630-
0x0002 => BigInt,
631-
0x0003 => Blob,
632-
0x0004 => Boolean,
633-
0x0005 => Counter,
634-
0x0006 => Decimal,
635-
0x0007 => Double,
636-
0x0008 => Float,
637-
0x0009 => Int,
638-
0x000B => Timestamp,
639-
0x000C => Uuid,
640-
0x000D => Text,
641-
0x000E => Varint,
642-
0x000F => Timeuuid,
643-
0x0010 => Inet,
644-
0x0011 => Date,
645-
0x0012 => Time,
646-
0x0013 => SmallInt,
647-
0x0014 => TinyInt,
648-
0x0015 => Duration,
649-
0x0020 => List(Box::new($deser_type(buf)?)),
650-
0x0021 => Map(Box::new($deser_type(buf)?), Box::new($deser_type(buf)?)),
651-
0x0022 => Set(Box::new($deser_type(buf)?)),
652-
0x0030 => {
653-
let keyspace_name =
654-
$read_string(buf).map_err(CqlTypeParseError::UdtKeyspaceNameParseError)?;
655-
let type_name =
656-
$read_string(buf).map_err(CqlTypeParseError::UdtNameParseError)?;
657-
let fields_size: usize = types::read_short(buf)
658-
.map_err(|err| CqlTypeParseError::UdtFieldsCountParseError(err.into()))?
659-
.into();
660-
661-
let mut field_types: Vec<(Cow<$l, str>, ColumnType)> =
662-
Vec::with_capacity(fields_size);
663-
664-
for _ in 0..fields_size {
665-
let field_name =
666-
$read_string(buf).map_err(CqlTypeParseError::UdtFieldNameParseError)?;
667-
let field_type = $deser_type(buf)?;
668-
669-
field_types.push((field_name.into(), field_type));
670-
}
671-
672-
UserDefinedType {
673-
type_name: type_name.into(),
674-
keyspace: keyspace_name.into(),
675-
field_types,
676-
}
677-
}
678-
0x0031 => {
679-
let len: usize = types::read_short(buf)
680-
.map_err(|err| CqlTypeParseError::TupleLengthParseError(err.into()))?
681-
.into();
682-
let mut types = Vec::with_capacity(len);
683-
for _ in 0..len {
684-
types.push($deser_type(buf)?);
685-
}
686-
Tuple(types)
687-
}
688-
id => {
689-
return Err(CqlTypeParseError::TypeNotImplemented(id));
690-
}
691-
})
606+
fn deser_type_generic<'frame, 'result, StrT: Into<Cow<'result, str>>>(
607+
buf: &mut &'frame [u8],
608+
read_string: fn(&mut &'frame [u8]) -> StdResult<StrT, LowLevelDeserializationError>,
609+
) -> StdResult<ColumnType<'result>, CqlTypeParseError> {
610+
use ColumnType::*;
611+
let id =
612+
types::read_short(buf).map_err(|err| CqlTypeParseError::TypeIdParseError(err.into()))?;
613+
Ok(match id {
614+
0x0000 => {
615+
// We use types::read_string instead of read_string argument here on purpose.
616+
// Chances are the underlying string is `...DurationType`, in which case
617+
// we don't need to allocate it at all. Only for Custom types
618+
// (which we don't support anyway) do we need to allocate.
619+
// OTOH, the macro argument function deserializes borrowed OR owned string;
620+
// here we want to always deserialize borrowed string.
621+
let type_str =
622+
types::read_string(buf).map_err(CqlTypeParseError::CustomTypeNameParseError)?;
623+
match type_str {
624+
"org.apache.cassandra.db.marshal.DurationType" => Duration,
625+
_ => Custom(type_str.to_owned().into()),
626+
}
692627
}
693-
};
628+
0x0001 => Ascii,
629+
0x0002 => BigInt,
630+
0x0003 => Blob,
631+
0x0004 => Boolean,
632+
0x0005 => Counter,
633+
0x0006 => Decimal,
634+
0x0007 => Double,
635+
0x0008 => Float,
636+
0x0009 => Int,
637+
0x000B => Timestamp,
638+
0x000C => Uuid,
639+
0x000D => Text,
640+
0x000E => Varint,
641+
0x000F => Timeuuid,
642+
0x0010 => Inet,
643+
0x0011 => Date,
644+
0x0012 => Time,
645+
0x0013 => SmallInt,
646+
0x0014 => TinyInt,
647+
0x0015 => Duration,
648+
0x0020 => List(Box::new(deser_type_generic(buf, read_string)?)),
649+
0x0021 => Map(
650+
Box::new(deser_type_generic(buf, read_string)?),
651+
Box::new(deser_type_generic(buf, read_string)?),
652+
),
653+
0x0022 => Set(Box::new(deser_type_generic(buf, read_string)?)),
654+
0x0030 => {
655+
let keyspace_name =
656+
read_string(buf).map_err(CqlTypeParseError::UdtKeyspaceNameParseError)?;
657+
let type_name = read_string(buf).map_err(CqlTypeParseError::UdtNameParseError)?;
658+
let fields_size: usize = types::read_short(buf)
659+
.map_err(|err| CqlTypeParseError::UdtFieldsCountParseError(err.into()))?
660+
.into();
661+
662+
let mut field_types: Vec<(Cow<'result, str>, ColumnType)> =
663+
Vec::with_capacity(fields_size);
664+
665+
for _ in 0..fields_size {
666+
let field_name =
667+
read_string(buf).map_err(CqlTypeParseError::UdtFieldNameParseError)?;
668+
let field_type = deser_type_generic(buf, read_string)?;
669+
670+
field_types.push((field_name.into(), field_type));
671+
}
672+
673+
UserDefinedType {
674+
type_name: type_name.into(),
675+
keyspace: keyspace_name.into(),
676+
field_types,
677+
}
678+
}
679+
0x0031 => {
680+
let len: usize = types::read_short(buf)
681+
.map_err(|err| CqlTypeParseError::TupleLengthParseError(err.into()))?
682+
.into();
683+
let mut types = Vec::with_capacity(len);
684+
for _ in 0..len {
685+
types.push(deser_type_generic(buf, read_string)?);
686+
}
687+
Tuple(types)
688+
}
689+
id => {
690+
return Err(CqlTypeParseError::TypeNotImplemented(id));
691+
}
692+
})
694693
}
695694

696-
generate_deser_type!(_deser_type_borrowed, 'frame, types::read_string);
695+
fn _deser_type_borrowed<'frame>(
696+
buf: &mut &'frame [u8],
697+
) -> StdResult<ColumnType<'frame>, CqlTypeParseError> {
698+
deser_type_generic(buf, |buf| types::read_string(buf))
699+
}
697700

698-
generate_deser_type!(deser_type_owned, 'static, |buf| types::read_string(buf).map(ToOwned::to_owned));
701+
fn deser_type_owned(buf: &mut &[u8]) -> StdResult<ColumnType<'static>, CqlTypeParseError> {
702+
deser_type_generic(buf, |buf| types::read_string(buf).map(ToOwned::to_owned))
703+
}
699704

700705
/// Deserializes a table spec, be it per-column one or a global one,
701706
/// in the borrowed form.

0 commit comments

Comments
 (0)