use bytes::{BufMut, Bytes, BytesMut};
use crate::buffer::WriteBuffer;
use crate::capabilities::Capabilities;
use crate::constants::{FetchOrientation, FunctionCode, MessageType, PacketType, PACKET_HEADER_SIZE};
use crate::error::Result;
#[derive(Debug)]
pub struct FetchMessage {
cursor_id: u16,
num_rows: u32,
orientation: Option<FetchOrientation>,
offset: i64,
}
impl FetchMessage {
pub fn new(cursor_id: u16, num_rows: u32) -> Self {
Self {
cursor_id,
num_rows,
orientation: None,
offset: 0,
}
}
pub fn new_scrollable(
cursor_id: u16,
num_rows: u32,
orientation: FetchOrientation,
offset: i64,
) -> Self {
Self {
cursor_id,
num_rows,
orientation: Some(orientation),
offset,
}
}
pub fn build_request(&self, _caps: &Capabilities) -> Result<Bytes> {
let mut buf = WriteBuffer::new();
buf.write_u8(MessageType::Function as u8)?;
buf.write_u8(FunctionCode::Fetch as u8)?;
buf.write_u8(0)?;
buf.write_ub4(self.cursor_id as u32)?;
buf.write_ub4(self.num_rows)?;
if let Some(orientation) = self.orientation {
buf.write_ub4(orientation as u32)?; buf.write_ub4(self.offset as u32)?; }
let payload = buf.freeze();
let packet_len = PACKET_HEADER_SIZE + payload.len();
let mut packet = BytesMut::with_capacity(packet_len);
packet.put_u16(packet_len as u16); packet.put_u16(0); packet.put_u8(PacketType::Data as u8);
packet.put_u8(0); packet.put_u16(0);
packet.put_u16(0);
packet.extend_from_slice(&payload);
Ok(packet.freeze())
}
pub fn cursor_id(&self) -> u16 {
self.cursor_id
}
pub fn num_rows(&self) -> u32 {
self.num_rows
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_fetch_message_creation() {
let msg = FetchMessage::new(1, 100);
assert_eq!(msg.cursor_id(), 1);
assert_eq!(msg.num_rows(), 100);
}
#[test]
fn test_fetch_message_builds_packet() {
let msg = FetchMessage::new(1, 100);
let caps = Capabilities::new();
let packet = msg.build_request(&caps).unwrap();
assert!(packet.len() > PACKET_HEADER_SIZE);
assert_eq!(packet[4], PacketType::Data as u8);
assert_eq!(packet[8], 0);
assert_eq!(packet[9], 0);
assert_eq!(packet[10], MessageType::Function as u8);
assert_eq!(packet[11], FunctionCode::Fetch as u8);
}
}