@@ -611,6 +611,10 @@ fn route(
611611 ( "POST" , "/api/v1/bind" ) => handle_bind ( body, format) ,
612612 ( "POST" , "/api/v1/bundle" ) => handle_bundle ( body, format) ,
613613
614+ // XOR — nanosecond zero-copy parity
615+ ( "POST" , "/api/v1/xor" ) => handle_xor ( body, format) ,
616+ ( "POST" , "/api/v1/xor/verify" ) => handle_xor_verify ( body, format) ,
617+
614618 // Search
615619 ( "POST" , "/api/v1/search/topk" ) => handle_topk ( body, state, format) ,
616620 ( "POST" , "/api/v1/search/threshold" ) => handle_threshold ( body, state, format) ,
@@ -1048,6 +1052,90 @@ fn handle_bundle(body: &str, format: ResponseFormat) -> Vec<u8> {
10481052 }
10491053}
10501054
1055+ /// POST /api/v1/xor — XOR two fingerprints. Single nanosecond operation.
1056+ fn handle_xor ( body : & str , format : ResponseFormat ) -> Vec < u8 > {
1057+ let a_str = extract_json_str ( body, "a" ) . unwrap_or_default ( ) ;
1058+ let b_str = extract_json_str ( body, "b" ) . unwrap_or_default ( ) ;
1059+ let fp_a = resolve_fingerprint ( & a_str) ;
1060+ let fp_b = resolve_fingerprint ( & b_str) ;
1061+
1062+ // XOR: one pass over 256 u64 words — nanoseconds
1063+ let mut result = Fingerprint :: zero ( ) ;
1064+ for i in 0 ..FINGERPRINT_WORDS {
1065+ result. words_mut ( ) [ i] = fp_a. words ( ) [ i] ^ fp_b. words ( ) [ i] ;
1066+ }
1067+
1068+ match format {
1069+ ResponseFormat :: Arrow => {
1070+ let schema = fingerprint_schema ( ) ;
1071+ let batch = RecordBatch :: try_new (
1072+ schema,
1073+ vec ! [
1074+ Arc :: new(
1075+ FixedSizeBinaryArray :: try_from_iter( std:: iter:: once( result. as_bytes( ) ) )
1076+ . unwrap( ) ,
1077+ ) as ArrayRef ,
1078+ Arc :: new( UInt32Array :: from( vec![ result. popcount( ) ] ) ) as ArrayRef ,
1079+ Arc :: new( Float32Array :: from( vec![ result. density( ) ] ) ) as ArrayRef ,
1080+ Arc :: new( UInt32Array :: from( vec![ FINGERPRINT_BITS as u32 ] ) ) as ArrayRef ,
1081+ ] ,
1082+ )
1083+ . unwrap ( ) ;
1084+ http_arrow ( 200 , & batch)
1085+ }
1086+ ResponseFormat :: Json => {
1087+ let json = format ! (
1088+ r#"{{"result":"{}","popcount":{},"density":{:.4},"op":"xor"}}"# ,
1089+ base64_encode( result. as_bytes( ) ) ,
1090+ result. popcount( ) ,
1091+ result. density( )
1092+ ) ;
1093+ http_json ( 200 , & json)
1094+ }
1095+ }
1096+ }
1097+
1098+ /// POST /api/v1/xor/verify — verify RAID-1 parity: A ⊕ B == 0 means identical
1099+ fn handle_xor_verify ( body : & str , format : ResponseFormat ) -> Vec < u8 > {
1100+ let a_str = extract_json_str ( body, "a" ) . unwrap_or_default ( ) ;
1101+ let b_str = extract_json_str ( body, "b" ) . unwrap_or_default ( ) ;
1102+ let fp_a = resolve_fingerprint ( & a_str) ;
1103+ let fp_b = resolve_fingerprint ( & b_str) ;
1104+
1105+ // XOR: identical fingerprints produce all zeros
1106+ let mut check = Fingerprint :: zero ( ) ;
1107+ for i in 0 ..FINGERPRINT_WORDS {
1108+ check. words_mut ( ) [ i] = fp_a. words ( ) [ i] ^ fp_b. words ( ) [ i] ;
1109+ }
1110+ let residual = check. popcount ( ) ;
1111+ let valid = residual == 0 ;
1112+
1113+ match format {
1114+ ResponseFormat :: Arrow => {
1115+ let schema = Arc :: new ( Schema :: new ( vec ! [
1116+ Field :: new( "valid" , DataType :: Boolean , false ) ,
1117+ Field :: new( "residual_popcount" , DataType :: UInt32 , false ) ,
1118+ ] ) ) ;
1119+ let batch = RecordBatch :: try_new (
1120+ schema,
1121+ vec ! [
1122+ Arc :: new( BooleanArray :: from( vec![ valid] ) ) as ArrayRef ,
1123+ Arc :: new( UInt32Array :: from( vec![ residual] ) ) as ArrayRef ,
1124+ ] ,
1125+ )
1126+ . unwrap ( ) ;
1127+ http_arrow ( 200 , & batch)
1128+ }
1129+ ResponseFormat :: Json => {
1130+ let json = format ! (
1131+ r#"{{"valid":{},"residual_popcount":{},"op":"xor_verify"}}"# ,
1132+ valid, residual
1133+ ) ;
1134+ http_json ( 200 , & json)
1135+ }
1136+ }
1137+ }
1138+
10511139fn handle_topk ( body : & str , state : & SharedState , format : ResponseFormat ) -> Vec < u8 > {
10521140 let query_str = extract_json_str ( body, "query" ) . unwrap_or_default ( ) ;
10531141 let k = extract_json_usize ( body, "k" ) . unwrap_or ( 10 ) ;
0 commit comments