Added UUID support in Ruby library
diff --git a/lib/rb/ext/compact_protocol.c b/lib/rb/ext/compact_protocol.c
index 62c17e1..8c864e8 100644
--- a/lib/rb/ext/compact_protocol.c
+++ b/lib/rb/ext/compact_protocol.c
@@ -20,10 +20,12 @@
 #include <ruby.h>
 #include <stdbool.h>
 #include <stdint.h>
+#include <string.h>
 #include <constants.h>
 #include <struct.h>
 #include <macros.h>
 #include <bytes.h>
+#include <protocol.h>
 
 #define LAST_ID(obj) FIX2INT(rb_ary_pop(rb_ivar_get(obj, last_field_id)))
 #define SET_LAST_ID(obj, val) rb_ary_push(rb_ivar_get(obj, last_field_id), val)
@@ -58,6 +60,7 @@
 static int CTYPE_SET            = 0x0A;
 static int CTYPE_MAP            = 0x0B;
 static int CTYPE_STRUCT         = 0x0C;
+static int CTYPE_UUID           = 0x0D;
 
 VALUE rb_thrift_compact_proto_write_i16(VALUE self, VALUE i16);
 
@@ -86,6 +89,8 @@
     return CTYPE_MAP;
   } else if (type == TTYPE_STRUCT) {
     return CTYPE_STRUCT;
+  } else if (type == TTYPE_UUID) {
+    return CTYPE_UUID;
   } else {
     char str[50];
     sprintf(str, "don't know what type: %d", type);
@@ -169,6 +174,7 @@
 VALUE rb_thrift_compact_proto_write_i32(VALUE self, VALUE i32);
 VALUE rb_thrift_compact_proto_write_string(VALUE self, VALUE str);
 VALUE rb_thrift_compact_proto_write_binary(VALUE self, VALUE buf);
+VALUE rb_thrift_compact_proto_write_uuid(VALUE self, VALUE uuid);
 
 VALUE rb_thrift_compact_proto_write_message_end(VALUE self) {
   return Qnil;
@@ -320,6 +326,46 @@
   return Qnil;
 }
 
+VALUE rb_thrift_compact_proto_write_uuid(VALUE self, VALUE uuid) {
+  if (NIL_P(uuid) || TYPE(uuid) != T_STRING) {
+    rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("UUID must be a string")));
+  }
+
+  VALUE transport = GET_TRANSPORT(self);
+  char bytes[16];
+  const char* str = RSTRING_PTR(uuid);
+  long len = RSTRING_LEN(uuid);
+
+  // Parse UUID string (format: "550e8400-e29b-41d4-a716-446655440000")
+  // Expected length: 36 characters (32 hex + 4 hyphens)
+  if (len != 36 || str[8] != '-' || str[13] != '-' || str[18] != '-' || str[23] != '-') {
+    rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Invalid UUID format")));
+  }
+
+  // Parse hex string to bytes using direct conversion, skipping hyphens
+  int byte_idx = 0;
+  for (int i = 0; i < len && byte_idx < 16; i++) {
+    if (str[i] == '-') continue;
+    if (i + 1 >= len || str[i + 1] == '-') break;
+
+    // Convert two hex characters to one byte
+    int high = hex_char_to_int(str[i]);
+    int low = hex_char_to_int(str[i + 1]);
+
+    if (high < 0 || low < 0) break;
+
+    bytes[byte_idx++] = (unsigned char)((high << 4) | low);
+    i++; // skip next char since we processed two
+  }
+
+  if (byte_idx != 16) {
+    rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Invalid UUID format")));
+  }
+
+  WRITE(transport, bytes, 16);
+  return Qnil;
+}
+
 //---------------------------------------
 // interface reading methods
 //---------------------------------------
@@ -331,6 +377,7 @@
 VALUE rb_thrift_compact_proto_read_byte(VALUE self);
 VALUE rb_thrift_compact_proto_read_i32(VALUE self);
 VALUE rb_thrift_compact_proto_read_i16(VALUE self);
+VALUE rb_thrift_compact_proto_read_uuid(VALUE self);
 
 static int8_t get_ttype(int8_t ctype) {
   if (ctype == TTYPE_STOP) {
@@ -357,6 +404,8 @@
     return TTYPE_MAP;
   } else if (ctype == CTYPE_STRUCT) {
     return TTYPE_STRUCT;
+  } else if (ctype == CTYPE_UUID) {
+    return TTYPE_UUID;
   } else {
     char str[50];
     sprintf(str, "don't know what type: %d", ctype);
@@ -396,13 +445,6 @@
   return zig_zag_to_int((int32_t)read_varint64(self));
 }
 
-static VALUE get_protocol_exception(VALUE code, VALUE message) {
-  VALUE args[2];
-  args[0] = code;
-  args[1] = message;
-  return rb_class_new_instance(2, (VALUE*)&args, protocol_exception_class);
-}
-
 VALUE rb_thrift_compact_proto_read_message_end(VALUE self) {
   return Qnil;
 }
@@ -565,6 +607,27 @@
   return READ(self, size);
 }
 
+VALUE rb_thrift_compact_proto_read_uuid(VALUE self) {
+  VALUE data = READ(self, 16);
+  const unsigned char* bytes = (const unsigned char*)RSTRING_PTR(data);
+
+  // Format as UUID string: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
+  char uuid_str[37];
+  char* p = uuid_str;
+
+  for (int i = 0; i < 16; i++) {
+    *p++ = int_to_hex_char((bytes[i] >> 4) & 0x0F);
+    *p++ = int_to_hex_char(bytes[i] & 0x0F);
+    if (i == 3 || i == 5 || i == 7 || i == 9) {
+      *p++ = '-';
+    }
+  }
+
+  *p = '\0';
+
+  return rb_str_new(uuid_str, 36);
+}
+
 static void Init_constants(void) {
   thrift_compact_protocol_class = rb_const_get(thrift_module, rb_intern("CompactProtocol"));
   rb_global_variable(&thrift_compact_protocol_class);
@@ -599,6 +662,7 @@
   rb_define_method(thrift_compact_protocol_class, "write_double",        rb_thrift_compact_proto_write_double, 1);
   rb_define_method(thrift_compact_protocol_class, "write_string",        rb_thrift_compact_proto_write_string, 1);
   rb_define_method(thrift_compact_protocol_class, "write_binary",        rb_thrift_compact_proto_write_binary, 1);
+  rb_define_method(thrift_compact_protocol_class, "write_uuid",          rb_thrift_compact_proto_write_uuid, 1);
 
   rb_define_method(thrift_compact_protocol_class, "write_message_end", rb_thrift_compact_proto_write_message_end, 0);
   rb_define_method(thrift_compact_protocol_class, "write_struct_begin", rb_thrift_compact_proto_write_struct_begin, 1);
@@ -622,6 +686,7 @@
   rb_define_method(thrift_compact_protocol_class, "read_double",         rb_thrift_compact_proto_read_double, 0);
   rb_define_method(thrift_compact_protocol_class, "read_string",         rb_thrift_compact_proto_read_string, 0);
   rb_define_method(thrift_compact_protocol_class, "read_binary",         rb_thrift_compact_proto_read_binary, 0);
+  rb_define_method(thrift_compact_protocol_class, "read_uuid",           rb_thrift_compact_proto_read_uuid, 0);
 
   rb_define_method(thrift_compact_protocol_class, "read_message_end", rb_thrift_compact_proto_read_message_end, 0);
   rb_define_method(thrift_compact_protocol_class, "read_struct_begin",  rb_thrift_compact_proto_read_struct_begin, 0);