1use crate::types::*;
4
5pub struct RequestBuilder {
7 method: String,
8 params: Option<serde_json::Value>,
9 id: Option<RequestId>,
10 correlation_id: Option<String>,
11}
12
13impl RequestBuilder {
14 pub fn new(method: impl Into<String>) -> Self {
16 Self {
17 method: method.into(),
18 params: None,
19 id: None,
20 correlation_id: Some(uuid::Uuid::new_v4().to_string()),
21 }
22 }
23
24 pub fn params(mut self, params: serde_json::Value) -> Self {
26 self.params = Some(params);
27 self
28 }
29
30 pub fn id(mut self, id: RequestId) -> Self {
32 self.id = Some(id);
33 self
34 }
35
36 pub fn correlation_id(mut self, correlation_id: String) -> Self {
38 self.correlation_id = Some(correlation_id);
39 self
40 }
41
42 pub fn build(self) -> Request {
44 Request {
45 jsonrpc: "2.0".to_string(),
46 method: self.method,
47 params: self.params,
48 id: self.id,
49 correlation_id: self.correlation_id,
50 }
51 }
52}
53
54pub struct ResponseBuilder {
56 result: Option<serde_json::Value>,
57 error: Option<Error>,
58 id: Option<RequestId>,
59 correlation_id: Option<String>,
60}
61
62impl ResponseBuilder {
63 pub fn new() -> Self {
65 Self {
66 result: None,
67 error: None,
68 id: None,
69 correlation_id: None,
70 }
71 }
72
73 pub fn success(mut self, result: serde_json::Value) -> Self {
75 self.result = Some(result);
76 self
77 }
78
79 pub fn error(mut self, error: Error) -> Self {
81 self.error = Some(error);
82 self
83 }
84
85 pub fn id(mut self, id: Option<RequestId>) -> Self {
87 self.id = id;
88 self
89 }
90 pub fn correlation_id(mut self, correlation_id: Option<String>) -> Self {
92 self.correlation_id = correlation_id;
93 self
94 }
95 pub fn build(self) -> Response {
97 Response {
98 jsonrpc: "2.0".to_string(),
99 result: self.result,
100 error: self.error,
101 id: self.id,
102 correlation_id: self.correlation_id,
103 }
104 }
105}
106
107pub struct NotificationBuilder {
109 method: String,
110 params: Option<serde_json::Value>,
111}
112
113impl NotificationBuilder {
114 pub fn new(method: impl Into<String>) -> Self {
116 Self {
117 method: method.into(),
118 params: None,
119 }
120 }
121
122 pub fn params(mut self, params: serde_json::Value) -> Self {
124 self.params = Some(params);
125 self
126 }
127
128 pub fn build(self) -> Notification {
130 Notification {
131 jsonrpc: "2.0".to_string(),
132 method: self.method,
133 params: self.params,
134 }
135 }
136}
137
138pub struct ErrorBuilder {
140 code: i32,
141 message: String,
142 data: Option<serde_json::Value>,
143}
144
145impl ErrorBuilder {
146 pub fn new(code: i32, message: impl Into<String>) -> Self {
148 Self {
149 code,
150 message: message.into(),
151 data: None,
152 }
153 }
154
155 pub fn data(mut self, data: serde_json::Value) -> Self {
157 self.data = Some(data);
158 self
159 }
160
161 pub fn build(self) -> Error {
163 Error {
164 code: self.code,
165 message: self.message,
166 data: self.data,
167 }
168 }
169}
170
171impl Default for ResponseBuilder {
172 fn default() -> Self {
173 Self::new()
174 }
175}
176
177#[cfg(any(feature = "tcp", feature = "tcp-stream", feature = "tcp-stream-tls"))]
179pub struct SecurityConfigBuilder {
180 max_connections: usize,
181 max_request_size: usize,
182 request_timeout: std::time::Duration,
183 idle_timeout: std::time::Duration,
184}
185
186#[cfg(any(feature = "tcp", feature = "tcp-stream", feature = "tcp-stream-tls"))]
187impl SecurityConfigBuilder {
188 pub fn new() -> Self {
190 Self {
191 max_connections: 1000,
192 max_request_size: 1024 * 1024, request_timeout: std::time::Duration::from_secs(30),
194 idle_timeout: std::time::Duration::from_secs(300), }
196 }
197
198 pub fn max_connections(mut self, max: usize) -> Self {
206 assert!(
207 max > 0 && max <= 100_000,
208 "max_connections must be between 1 and 100000"
209 );
210 self.max_connections = max;
211 self
212 }
213
214 pub fn max_request_size(mut self, size: usize) -> Self {
222 assert!(
223 (1024..=100 * 1024 * 1024).contains(&size),
224 "max_request_size must be between 1KB and 100MB"
225 );
226 self.max_request_size = size;
227 self
228 }
229
230 pub fn request_timeout(mut self, timeout: std::time::Duration) -> Self {
238 assert!(
239 (1..=300).contains(&timeout.as_secs()),
240 "request_timeout must be between 1 second and 5 minutes"
241 );
242 self.request_timeout = timeout;
243 self
244 }
245
246 pub fn idle_timeout(mut self, timeout: std::time::Duration) -> Self {
254 assert!(
255 (10..=3600).contains(&timeout.as_secs()),
256 "idle_timeout must be between 10 seconds and 1 hour"
257 );
258 self.idle_timeout = timeout;
259 self
260 }
261
262 pub fn build(self) -> crate::transports::SecurityConfig {
264 tracing::info!(
265 max_connections = self.max_connections,
266 max_request_size = self.max_request_size,
267 request_timeout_secs = self.request_timeout.as_secs(),
268 idle_timeout_secs = self.idle_timeout.as_secs(),
269 "creating security configuration"
270 );
271
272 crate::transports::SecurityConfig {
273 max_connections: self.max_connections,
274 max_request_size: self.max_request_size,
275 request_timeout: self.request_timeout,
276 idle_timeout: self.idle_timeout,
277 }
278 }
279}
280
281#[cfg(any(feature = "tcp", feature = "tcp-stream", feature = "tcp-stream-tls"))]
282impl Default for SecurityConfigBuilder {
283 fn default() -> Self {
284 Self::new()
285 }
286}
287
288#[cfg(all(
289 test,
290 any(feature = "tcp", feature = "tcp-stream", feature = "tcp-stream-tls")
291))]
292mod tests {
293 use super::*;
294
295 #[test]
296 #[should_panic(expected = "max_connections must be between 1 and 100000")]
297 fn test_max_connections_zero_panics() {
298 SecurityConfigBuilder::new().max_connections(0).build();
299 }
300
301 #[test]
302 fn test_valid_security_config() {
303 let config = SecurityConfigBuilder::new()
304 .max_connections(500)
305 .max_request_size(2 * 1024 * 1024)
306 .request_timeout(std::time::Duration::from_secs(60))
307 .idle_timeout(std::time::Duration::from_secs(600))
308 .build();
309
310 assert_eq!(config.max_connections, 500);
311 assert_eq!(config.max_request_size, 2 * 1024 * 1024);
312 }
313
314 #[test]
316 fn test_request_builder_basic() {
317 let request = RequestBuilder::new("test_method").build();
318 assert_eq!(request.method, "test_method");
319 assert_eq!(request.jsonrpc, "2.0");
320 assert!(request.correlation_id.is_some());
321 }
322
323 #[test]
324 fn test_request_builder_with_params() {
325 let params = serde_json::json!({"key": "value"});
326 let request = RequestBuilder::new("method").params(params.clone()).build();
327 assert_eq!(request.params, Some(params));
328 }
329
330 #[test]
331 fn test_request_builder_with_id() {
332 let id = serde_json::json!(123);
333 let request = RequestBuilder::new("method").id(id.clone()).build();
334 assert_eq!(request.id, Some(id));
335 }
336
337 #[test]
338 fn test_request_builder_with_correlation_id() {
339 let correlation_id = "custom-correlation-id".to_string();
340 let request = RequestBuilder::new("method")
341 .correlation_id(correlation_id.clone())
342 .build();
343 assert_eq!(request.correlation_id, Some(correlation_id));
344 }
345
346 #[test]
347 fn test_request_builder_complete() {
348 let params = serde_json::json!([1, 2, 3]);
349 let id = serde_json::json!(456);
350 let correlation_id = "test-corr-id".to_string();
351
352 let request = RequestBuilder::new("complete_method")
353 .params(params.clone())
354 .id(id.clone())
355 .correlation_id(correlation_id.clone())
356 .build();
357
358 assert_eq!(request.method, "complete_method");
359 assert_eq!(request.params, Some(params));
360 assert_eq!(request.id, Some(id));
361 assert_eq!(request.correlation_id, Some(correlation_id));
362 }
363
364 #[test]
366 fn test_response_builder_success() {
367 let result = serde_json::json!({"status": "ok"});
368 let id = serde_json::json!(1);
369
370 let response = ResponseBuilder::new()
371 .success(result.clone())
372 .id(Some(id.clone()))
373 .build();
374
375 assert_eq!(response.result, Some(result));
376 assert!(response.error.is_none());
377 assert_eq!(response.id, Some(id));
378 }
379
380 #[test]
381 fn test_response_builder_error() {
382 let error =
383 crate::ErrorBuilder::new(crate::error_codes::INVALID_REQUEST, "Invalid request")
384 .build();
385 let id = serde_json::json!(2);
386
387 let response = ResponseBuilder::new()
388 .error(error.clone())
389 .id(Some(id.clone()))
390 .build();
391
392 assert!(response.result.is_none());
393 assert_eq!(
394 response.error.unwrap().code,
395 crate::error_codes::INVALID_REQUEST
396 );
397 assert_eq!(response.id, Some(id));
398 }
399
400 #[test]
401 fn test_response_builder_with_correlation_id_basic() {
402 let correlation_id = "resp-corr-id".to_string();
403 let response = ResponseBuilder::new()
404 .success(serde_json::json!("ok"))
405 .correlation_id(Some(correlation_id.clone()))
406 .build();
407
408 assert_eq!(response.correlation_id, Some(correlation_id));
409 }
410
411 #[test]
412 fn test_response_builder_jsonrpc_version() {
413 let response = ResponseBuilder::new()
414 .success(serde_json::json!("test"))
415 .build();
416 assert_eq!(response.jsonrpc, "2.0");
417 }
418
419 #[test]
421 fn test_notification_builder_basic() {
422 let notification = NotificationBuilder::new("event").build();
423 assert_eq!(notification.method, "event");
424 assert_eq!(notification.jsonrpc, "2.0");
425 assert!(notification.params.is_none());
426 }
427
428 #[test]
429 fn test_notification_builder_with_params() {
430 let params = serde_json::json!({"event": "update"});
431 let notification = NotificationBuilder::new("notify")
432 .params(params.clone())
433 .build();
434 assert_eq!(notification.params, Some(params));
435 }
436
437 #[test]
439 fn test_error_builder_basic() {
440 let error = ErrorBuilder::new(crate::error_codes::INVALID_REQUEST, "Test error").build();
441 assert_eq!(error.code, crate::error_codes::INVALID_REQUEST);
442 assert_eq!(error.message, "Test error");
443 assert!(error.data.is_none());
444 }
445
446 #[test]
447 fn test_error_builder_with_data() {
448 let data = serde_json::json!({"detail": "more info"});
449 let error = ErrorBuilder::new(crate::error_codes::INTERNAL_ERROR, "Error")
450 .data(data.clone())
451 .build();
452 assert_eq!(error.data, Some(data));
453 }
454
455 #[test]
456 fn test_error_builder_string_conversion() {
457 let error = ErrorBuilder::new(
458 crate::error_codes::INTERNAL_ERROR,
459 String::from("Dynamic error"),
460 )
461 .build();
462 assert_eq!(error.message, "Dynamic error");
463 }
464
465 #[test]
467 #[should_panic(expected = "max_request_size must be between")]
468 fn test_security_config_request_size_too_small() {
469 SecurityConfigBuilder::new()
470 .max_request_size(512) .build();
472 }
473
474 #[test]
475 #[should_panic(expected = "max_request_size must be between")]
476 fn test_security_config_request_size_too_large() {
477 SecurityConfigBuilder::new()
478 .max_request_size(200 * 1024 * 1024) .build();
480 }
481
482 #[test]
483 #[should_panic(expected = "max_connections must be between")]
484 fn test_security_config_connections_too_large() {
485 SecurityConfigBuilder::new()
486 .max_connections(150_000)
487 .build();
488 }
489
490 #[test]
491 fn test_security_config_boundary_values() {
492 let config_min = SecurityConfigBuilder::new()
494 .max_connections(1)
495 .max_request_size(1024)
496 .build();
497 assert_eq!(config_min.max_connections, 1);
498 assert_eq!(config_min.max_request_size, 1024);
499
500 let config_max = SecurityConfigBuilder::new()
502 .max_connections(100_000)
503 .max_request_size(100 * 1024 * 1024)
504 .build();
505 assert_eq!(config_max.max_connections, 100_000);
506 assert_eq!(config_max.max_request_size, 100 * 1024 * 1024);
507 }
508
509 #[test]
510 fn test_security_config_timeouts() {
511 let request_timeout = std::time::Duration::from_secs(45);
512 let idle_timeout = std::time::Duration::from_secs(900);
513
514 let config = SecurityConfigBuilder::new()
515 .request_timeout(request_timeout)
516 .idle_timeout(idle_timeout)
517 .build();
518
519 assert_eq!(config.request_timeout, request_timeout);
520 assert_eq!(config.idle_timeout, idle_timeout);
521 }
522
523 #[test]
524 fn test_security_config_defaults() {
525 let config = SecurityConfigBuilder::new().build();
526 assert_eq!(config.max_connections, 1000);
527 assert_eq!(config.max_request_size, 1024 * 1024);
528 assert_eq!(config.request_timeout, std::time::Duration::from_secs(30));
529 assert_eq!(config.idle_timeout, std::time::Duration::from_secs(300));
530 }
531
532 #[test]
533 fn test_security_config_builder_default() {
534 let builder = SecurityConfigBuilder::default();
535 let config = builder.build();
536 assert_eq!(config.max_connections, 1000);
537 }
538
539 #[test]
540 #[should_panic(expected = "request_timeout must be between")]
541 fn test_security_config_timeout_too_short() {
542 SecurityConfigBuilder::new()
543 .request_timeout(std::time::Duration::from_millis(500))
544 .build();
545 }
546
547 #[test]
548 #[should_panic(expected = "request_timeout must be between")]
549 fn test_security_config_timeout_too_long() {
550 SecurityConfigBuilder::new()
551 .request_timeout(std::time::Duration::from_secs(400))
552 .build();
553 }
554
555 #[test]
556 #[should_panic(expected = "idle_timeout must be between")]
557 fn test_security_config_idle_timeout_too_short() {
558 SecurityConfigBuilder::new()
559 .idle_timeout(std::time::Duration::from_secs(5))
560 .build();
561 }
562
563 #[test]
564 #[should_panic(expected = "idle_timeout must be between")]
565 fn test_security_config_idle_timeout_too_long() {
566 SecurityConfigBuilder::new()
567 .idle_timeout(std::time::Duration::from_secs(4000))
568 .build();
569 }
570
571 #[test]
572 fn test_request_builder_method_set() {
573 let request = RequestBuilder::new("test_method").build();
574 assert_eq!(request.method, "test_method");
575 }
576
577 #[test]
578 fn test_request_builder_auto_correlation_id() {
579 let request = RequestBuilder::new("test").build();
580 assert!(request.correlation_id.is_some());
581 }
582
583 #[test]
584 fn test_request_builder_custom_correlation_id() {
585 let custom_id = "custom-correlation-123".to_string();
586 let request = RequestBuilder::new("test")
587 .correlation_id(custom_id.clone())
588 .build();
589 assert_eq!(request.correlation_id, Some(custom_id));
590 }
591
592 #[test]
593 fn test_request_builder_full_chain() {
594 let request = RequestBuilder::new("full_test")
595 .params(serde_json::json!({"key": "value"}))
596 .id(serde_json::json!(123))
597 .correlation_id("corr-123".to_string())
598 .build();
599
600 assert_eq!(request.method, "full_test");
601 assert!(request.params.is_some());
602 assert_eq!(request.id, Some(serde_json::json!(123)));
603 assert_eq!(request.correlation_id, Some("corr-123".to_string()));
604 }
605
606 #[test]
607 fn test_response_builder_default_trait() {
608 let builder = ResponseBuilder::default();
609 let response = builder.build();
610 assert_eq!(response.jsonrpc, "2.0");
611 }
612
613 #[test]
614 fn test_response_builder_success_with_null() {
615 let response = ResponseBuilder::new()
616 .success(serde_json::json!(null))
617 .build();
618 assert_eq!(response.result, Some(serde_json::json!(null)));
619 }
620
621 #[test]
622 fn test_response_builder_with_correlation_id() {
623 let corr_id = "test-correlation".to_string();
624 let response = ResponseBuilder::new()
625 .success(serde_json::json!(42))
626 .correlation_id(Some(corr_id.clone()))
627 .build();
628 assert_eq!(response.correlation_id, Some(corr_id));
629 }
630
631 #[test]
632 fn test_response_builder_full_error() {
633 let error = ErrorBuilder::new(crate::error_codes::INTERNAL_ERROR, "Custom error")
634 .data(serde_json::json!({"field": "value"}))
635 .build();
636
637 let response = ResponseBuilder::new()
638 .error(error.clone())
639 .id(Some(serde_json::json!(1)))
640 .correlation_id(Some("err-corr".to_string()))
641 .build();
642
643 assert!(response.result.is_none());
644 assert_eq!(response.error, Some(error));
645 assert_eq!(response.id, Some(serde_json::json!(1)));
646 assert_eq!(response.correlation_id, Some("err-corr".to_string()));
647 }
648
649 #[test]
650 fn test_notification_builder_string_method() {
651 let notification = NotificationBuilder::new(String::from("dynamic_method")).build();
652 assert_eq!(notification.method, "dynamic_method");
653 }
654
655 #[test]
656 fn test_error_builder_multiple_data() {
657 let error = ErrorBuilder::new(crate::error_codes::INTERNAL_ERROR, "Error")
658 .data(serde_json::json!({"key1": "value1"}))
659 .build();
660
661 assert!(error.data.is_some());
662 let data = error.data.unwrap();
663 assert_eq!(data["key1"], "value1");
664 }
665}
666
667#[cfg(feature = "streaming")]
669pub struct StreamResponseBuilder {
670 result: Option<serde_json::Value>,
671 error: Option<Error>,
672 id: RequestId,
673 stream_id: String,
674 stream_status: Option<crate::streaming::StreamStatus>,
675}
676
677#[cfg(feature = "streaming")]
678impl StreamResponseBuilder {
679 pub fn new(stream_id: impl Into<String>, id: RequestId) -> Self {
681 Self {
682 result: None,
683 error: None,
684 id,
685 stream_id: stream_id.into(),
686 stream_status: None,
687 }
688 }
689
690 pub fn success(mut self, result: serde_json::Value) -> Self {
692 self.result = Some(result);
693 self.stream_status = Some(crate::streaming::StreamStatus::Active);
694 self
695 }
696
697 pub fn error(mut self, error: Error) -> Self {
699 self.error = Some(error);
700 self.stream_status = Some(crate::streaming::StreamStatus::Error);
701 self
702 }
703
704 pub fn status(mut self, status: crate::streaming::StreamStatus) -> Self {
706 self.stream_status = Some(status);
707 self
708 }
709
710 pub fn build(self) -> crate::streaming::StreamResponse {
712 crate::streaming::StreamResponse {
713 jsonrpc: "2.0".to_string(),
714 result: self.result,
715 error: self.error,
716 id: self.id,
717 stream_id: self.stream_id,
718 stream_status: self.stream_status,
719 }
720 }
721}