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