| 
									
										
										
										
											2024-01-12 09:53:53 -08:00
										 |  |  | # typed: strict | 
					
						
							| 
									
										
										
										
											2023-11-29 15:18:14 +00:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-12 09:53:53 -08:00
										 |  |  | require "extend/object/duplicable" | 
					
						
							| 
									
										
										
										
											2023-11-29 15:18:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Object | 
					
						
							|  |  |  |   # Returns a deep copy of object if it's duplicable. If it's | 
					
						
							|  |  |  |   # not duplicable, returns +self+. | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   #   object = Object.new | 
					
						
							|  |  |  |   #   dup    = object.deep_dup | 
					
						
							|  |  |  |   #   dup.instance_variable_set(:@a, 1) | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   #   object.instance_variable_defined?(:@a) # => false | 
					
						
							|  |  |  |   #   dup.instance_variable_defined?(:@a)    # => true | 
					
						
							| 
									
										
										
										
											2024-01-12 09:53:53 -08:00
										 |  |  |   sig { returns(T.self_type) } | 
					
						
							| 
									
										
										
										
											2024-01-12 15:17:12 -08:00
										 |  |  |   def deep_dup | 
					
						
							|  |  |  |     duplicable? ? dup : self | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2023-11-29 15:18:14 +00:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Array | 
					
						
							|  |  |  |   # Returns a deep copy of array. | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   #   array = [1, [2, 3]] | 
					
						
							|  |  |  |   #   dup   = array.deep_dup | 
					
						
							|  |  |  |   #   dup[1][2] = 4 | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   #   array[1][2] # => nil | 
					
						
							|  |  |  |   #   dup[1][2]   # => 4 | 
					
						
							| 
									
										
										
										
											2024-01-12 09:53:53 -08:00
										 |  |  |   sig { returns(T.self_type) } | 
					
						
							| 
									
										
										
										
											2024-01-12 15:17:12 -08:00
										 |  |  |   def deep_dup | 
					
						
							|  |  |  |     T.unsafe(self).map(&:deep_dup) | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2023-11-29 15:18:14 +00:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Hash | 
					
						
							|  |  |  |   # Returns a deep copy of hash. | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   #   hash = { a: { b: 'b' } } | 
					
						
							|  |  |  |   #   dup  = hash.deep_dup | 
					
						
							|  |  |  |   #   dup[:a][:c] = 'c' | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   #   hash[:a][:c] # => nil | 
					
						
							|  |  |  |   #   dup[:a][:c]  # => "c" | 
					
						
							| 
									
										
										
										
											2024-01-12 09:53:53 -08:00
										 |  |  |   sig { returns(T.self_type) } | 
					
						
							| 
									
										
										
										
											2023-11-29 15:18:14 +00:00
										 |  |  |   def deep_dup | 
					
						
							|  |  |  |     hash = dup | 
					
						
							|  |  |  |     each_pair do |key, value| | 
					
						
							| 
									
										
										
										
											2024-01-12 09:53:53 -08:00
										 |  |  |       case key | 
					
						
							|  |  |  |       when ::String, ::Symbol | 
					
						
							|  |  |  |         hash[key] = T.unsafe(value).deep_dup | 
					
						
							| 
									
										
										
										
											2023-11-29 15:18:14 +00:00
										 |  |  |       else | 
					
						
							|  |  |  |         hash.delete(key) | 
					
						
							| 
									
										
										
										
											2024-01-12 09:53:53 -08:00
										 |  |  |         hash[T.unsafe(key).deep_dup] = T.unsafe(value).deep_dup | 
					
						
							| 
									
										
										
										
											2023-11-29 15:18:14 +00:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     hash | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							| 
									
										
										
										
											2024-01-12 09:53:53 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Module | 
					
						
							|  |  |  |   # Returns a copy of module or class if it's anonymous. If it's | 
					
						
							|  |  |  |   # named, returns +self+. | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   #   Object.deep_dup == Object # => true | 
					
						
							|  |  |  |   #   klass = Class.new | 
					
						
							|  |  |  |   #   klass.deep_dup == klass # => false | 
					
						
							|  |  |  |   sig { returns(T.self_type) } | 
					
						
							|  |  |  |   def deep_dup | 
					
						
							|  |  |  |     if name.nil? | 
					
						
							|  |  |  |       super | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       self | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |