junkfood 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +11 -0
- data/.gitignore +6 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +76 -0
- data/LICENSE +202 -0
- data/NOTICE +4 -0
- data/README.md +375 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/junkfood.gemspec +147 -0
- data/lib/junkfood/adler32.rb +102 -0
- data/lib/junkfood/adler32_pure.rb +112 -0
- data/lib/junkfood/assert.rb +75 -0
- data/lib/junkfood/base32.rb +198 -0
- data/lib/junkfood/ceb/base_command.rb +62 -0
- data/lib/junkfood/ceb/base_event.rb +42 -0
- data/lib/junkfood/ceb/bus.rb +152 -0
- data/lib/junkfood/ceb/executors/command_executor.rb +44 -0
- data/lib/junkfood/ceb/executors/delayed_job_command_executor.rb +61 -0
- data/lib/junkfood/ceb/executors/event_executor.rb +35 -0
- data/lib/junkfood/ceb/executors.rb +25 -0
- data/lib/junkfood/ceb.rb +27 -0
- data/lib/junkfood/one_time.rb +247 -0
- data/lib/junkfood/paperclip_string_io.rb +66 -0
- data/lib/junkfood/settings.rb +67 -0
- data/lib/junkfood.rb +29 -0
- data/spec/.rspec +1 -0
- data/spec/junkfood/adler32_pure_spec.rb +16 -0
- data/spec/junkfood/adler32_spec.rb +16 -0
- data/spec/junkfood/assert_spec.rb +84 -0
- data/spec/junkfood/base32_spec.rb +39 -0
- data/spec/junkfood/ceb/base_command_spec.rb +73 -0
- data/spec/junkfood/ceb/base_event_spec.rb +67 -0
- data/spec/junkfood/ceb/bus_spec.rb +153 -0
- data/spec/junkfood/ceb/executors/command_executor_spec.rb +24 -0
- data/spec/junkfood/ceb/executors/delayed_job_command_executor_spec.rb +5 -0
- data/spec/junkfood/ceb/executors/event_executor_spec.rb +18 -0
- data/spec/junkfood/one_time_spec.rb +167 -0
- data/spec/junkfood/paperclip_string_io_spec.rb +40 -0
- data/spec/junkfood/settings_spec.rb +7 -0
- data/spec/junkfood_spec.rb +4 -0
- data/spec/spec_helper.rb +20 -0
- metadata +372 -0
data/README.md
ADDED
@@ -0,0 +1,375 @@
|
|
1
|
+
Junkfood
|
2
|
+
========
|
3
|
+
|
4
|
+
Junkfood is a mesh of different modules and classes that I found useful
|
5
|
+
for various projects. I combined them all into this all-in-one library
|
6
|
+
because each included component isn't big enough (or comprehensive
|
7
|
+
enough) to warrant its own fully managed gem library.
|
8
|
+
|
9
|
+
Components
|
10
|
+
----------
|
11
|
+
|
12
|
+
* Adler32
|
13
|
+
* Assert
|
14
|
+
* Base32
|
15
|
+
* CEB - "Command-Event Busing" for Command-Query Responsibility Separation
|
16
|
+
* OneTime - HMAC One Time Passwords
|
17
|
+
* PaperclipStringIO
|
18
|
+
* Settings
|
19
|
+
|
20
|
+
Adler32
|
21
|
+
=======
|
22
|
+
|
23
|
+
[Adler-32](http://en.wikipedia.org/wiki/Adler-32) is a checksum algorithm
|
24
|
+
which was invented by Mark Adler. Compared to a cyclic redundancy check
|
25
|
+
of the same length, it trades reliability for speed. Adler-32 is more
|
26
|
+
reliable than Fletcher-16, and slightly less reliable than Fletcher-32.
|
27
|
+
|
28
|
+
Junkfood provides two implementations of Adler-32 in Ruby:
|
29
|
+
|
30
|
+
* Adler32 uses the Zlib library to do the checksum.
|
31
|
+
* Adler32Pure is a pure Ruby implementation of Adler-32 ported
|
32
|
+
from the [Pysync library](http://freshmeat.net/projects/pysync/).
|
33
|
+
|
34
|
+
Example:
|
35
|
+
|
36
|
+
adler32 = Junkfood::Adler32.new('Wikipedia') # Or Junkfood::Adler32Pure.new
|
37
|
+
puts adler32.digest #=> 300286872
|
38
|
+
|
39
|
+
adler32 = Junkfood::Adler32.new
|
40
|
+
digest = adler32.update 'Wikipedia' #=> 300286872
|
41
|
+
adler32.digest #=> 300286872
|
42
|
+
|
43
|
+
Assert
|
44
|
+
======
|
45
|
+
|
46
|
+
A very simple assertions module to be a drop in "dumb down" replacement
|
47
|
+
for the 'wrong' assertion library. It is here just to be my own fallback
|
48
|
+
implementation for cases where I may not actually want to install the
|
49
|
+
[wrong gem](<http://rubygems.org/gems/wrong>) yet still like that
|
50
|
+
style of assertions.
|
51
|
+
|
52
|
+
require 'junkfood/assert'
|
53
|
+
class MyClass
|
54
|
+
include Junkfood::Assert
|
55
|
+
|
56
|
+
def my_method
|
57
|
+
testcase = true
|
58
|
+
assert { testcase == true } # This will flow through.
|
59
|
+
assert { testcase == false } # This will raise an error.
|
60
|
+
assert('My Custom Error Message') {
|
61
|
+
testcase == false
|
62
|
+
}
|
63
|
+
rescue Junkfood::Assert::AssertionFailedError => e
|
64
|
+
puts e
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
Base32
|
69
|
+
======
|
70
|
+
|
71
|
+
A ruby implementation of [RFC4648](http://http://tools.ietf.org/html/rfc4648).
|
72
|
+
This class requires at least version Ruby 1.9 because it uses the new
|
73
|
+
String Encodings internally.
|
74
|
+
|
75
|
+
require 'junkfood/base32'
|
76
|
+
|
77
|
+
# Base32 uses StringIO objects by default.
|
78
|
+
io = Junkfood::Base32.encode 'MyBinaryStringData'
|
79
|
+
puts io.string
|
80
|
+
puts io.string.encoding #=> Encoding::ASCII
|
81
|
+
|
82
|
+
io = Junkfood::Base32.decode 'MyBase32StringData'
|
83
|
+
puts io.string
|
84
|
+
puts io.string.encoding #=> Encoding::BINARY
|
85
|
+
|
86
|
+
# The IO can be any object that conforms to Ruby IO.
|
87
|
+
# The returned io is the same file passed to output.
|
88
|
+
io = Junkfood::Base32.encode 'BinaryData', :output => open('out.b32', 'w')
|
89
|
+
io = Junkfood::Base32.decode 'Base32Data', :output => open('out.bin', 'w')
|
90
|
+
|
91
|
+
# Input is any object that conforms to #each_byte. This includes
|
92
|
+
# Strings and File IOs.
|
93
|
+
io = Junkfood::Base32.encode(
|
94
|
+
open('in.bin', 'r'),
|
95
|
+
:output => open('out.b32', 'w'))
|
96
|
+
io.close
|
97
|
+
io = Junkfood::Base32.decode(
|
98
|
+
open('in.b32', 'r'),
|
99
|
+
:output => open('out.bin', 'w'))
|
100
|
+
io.close
|
101
|
+
|
102
|
+
|
103
|
+
Command Event Busing (CEB)
|
104
|
+
==========================
|
105
|
+
|
106
|
+
This component is meant to support Command-Query Responsibility Separation.
|
107
|
+
|
108
|
+
CEB is comprised of three major parts:
|
109
|
+
|
110
|
+
* The Base Models (BaseCommand, BaseEvent)
|
111
|
+
* The Bus (Bus)
|
112
|
+
* The Executors (CommandExecutor, EventExecutor)
|
113
|
+
|
114
|
+
The Base Models implement the foundation of Commands and Events in CQRS;
|
115
|
+
the Bus instantiates Command/Event from the parameters, validates
|
116
|
+
(using ActiveModel valid?) the Command/Event and drives its process with
|
117
|
+
the associated executors; executors (one per Command or Event bus) runs
|
118
|
+
the specific process to handle a command or event.
|
119
|
+
|
120
|
+
Commands are both data representation and handler code for its function.
|
121
|
+
Events are just statements of fact about changes in the system.
|
122
|
+
|
123
|
+
CEB Base Models
|
124
|
+
---------------
|
125
|
+
|
126
|
+
BaseCommand and BaseEvent uses MongoDb via [mongoid](http://mongoid.org/).
|
127
|
+
Command and Event models SHOULD implement the ActiveModel interface; they
|
128
|
+
must at least implement the subset of features as described by the
|
129
|
+
RSpec tests in base_command_spec.rb and base_event_spec.rb.
|
130
|
+
|
131
|
+
These base models:
|
132
|
+
|
133
|
+
1. Provide persistence for audit logs.
|
134
|
+
2. Provide the base help to represent Commands and Events in our framework.
|
135
|
+
Users will subclass BaseCommand and BaseEvent to model their domain.
|
136
|
+
3. Be the "standard contract" for others that want to implement their
|
137
|
+
base models. E.g. - Use ActiveRecord instead of Mongoid.
|
138
|
+
|
139
|
+
Subclasses of BaseCommand that implement their own `perform` method
|
140
|
+
SHOULD return the Event (or list of Events) published when said `perform`
|
141
|
+
method was executed.
|
142
|
+
|
143
|
+
CEB Executors
|
144
|
+
-------------
|
145
|
+
|
146
|
+
We implement helpers for the Command Bus and Event Bus part of CQRS.
|
147
|
+
So we have two default executors to handle the logic for those two buses.
|
148
|
+
|
149
|
+
* CommandExecutor
|
150
|
+
* EventExecutor
|
151
|
+
|
152
|
+
CommandExecutor is the default command bus executor that:
|
153
|
+
|
154
|
+
1. just calls save! on the instantiated command, raising errors on failure.
|
155
|
+
2. executes the command's perform method (with the assumption that
|
156
|
+
the bus validated the command beforehand).
|
157
|
+
3. the return value from `perform` is passed back to the bus send_command
|
158
|
+
or send_event call.
|
159
|
+
|
160
|
+
Alternative CommandExecutors (e.g. - for DelayedJob) may just use its
|
161
|
+
own mechanisms to queue up the Command (most likely using the Command's
|
162
|
+
to_json serialization) for later execution. In this case, the executor's
|
163
|
+
call should return nil or false to the bus. This return value is convention
|
164
|
+
to signal this delayed execution to the requester.
|
165
|
+
|
166
|
+
EventExecutor is the default event bus executor that:
|
167
|
+
|
168
|
+
1. just calls save! on the instantiated event, raising errors on failure.
|
169
|
+
2. TODO: publishes the serialized Event (to_json) over a PubSub network such
|
170
|
+
as zeromq or webhooks.
|
171
|
+
|
172
|
+
CEB Example
|
173
|
+
-----------
|
174
|
+
|
175
|
+
class WidgetCreateCommand < Junkfood::Ceb::BaseCommand
|
176
|
+
|
177
|
+
field :color, :type => String, :default => 'red'
|
178
|
+
|
179
|
+
def perform
|
180
|
+
# Do creation. Update DDD aggregate root, or ActiveRecord State,
|
181
|
+
# or whatever is used to keep application state.
|
182
|
+
success = true
|
183
|
+
|
184
|
+
# Now we publish events based on what happened.
|
185
|
+
# Normally, there is a one-to-one relation between the number of
|
186
|
+
# commands performed to the number of event published.
|
187
|
+
if success
|
188
|
+
event, result = send_event(
|
189
|
+
'widget_created',
|
190
|
+
:command_id => self.id,
|
191
|
+
:color => color,
|
192
|
+
:other_widget_info => 'to be determined')
|
193
|
+
else
|
194
|
+
event, result = send_event(
|
195
|
+
'widget_creation_failed',
|
196
|
+
:command_id => self.id,
|
197
|
+
:error => 'some determined error',
|
198
|
+
:other_widget_info => 'to be determined')
|
199
|
+
end
|
200
|
+
|
201
|
+
# This is convention. Commands SHOULD return the event, or list of
|
202
|
+
# events, that it published in the execution of this perform method.
|
203
|
+
return event
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class WidgetCreatedEvent < Junkfood::Ceb::BaseEvent
|
208
|
+
field :color, :type => String
|
209
|
+
field :other_widget_info, :type => String
|
210
|
+
end
|
211
|
+
|
212
|
+
class WidgetCreationFailedEvent < Junkfood::Ceb::BaseEvent
|
213
|
+
field :error_info, :type => String
|
214
|
+
field :other_widget_info, :type => String
|
215
|
+
end
|
216
|
+
|
217
|
+
class ApplicationController < ActionController::Base
|
218
|
+
include Junkfood::Ceb::Bus
|
219
|
+
acts_as_command_bus
|
220
|
+
end
|
221
|
+
|
222
|
+
class WidgetController < ApplicationController
|
223
|
+
def create
|
224
|
+
# params['widget'] is our posted form data that conforms to the Rails
|
225
|
+
# way of doing things for ActiveModel. This eliminates hassle for
|
226
|
+
# custom parsing, data handling.
|
227
|
+
|
228
|
+
# Create a command (WidgetCreateCommand) and puts it onto the bus
|
229
|
+
# for execution. The command created is returned along with
|
230
|
+
# published events by the command.
|
231
|
+
command, events = send_command 'widget_create', params['widget']
|
232
|
+
|
233
|
+
if command.valid?
|
234
|
+
# The command is correctly formed, so the backend executors will
|
235
|
+
# execute it in the future (or already has executed it).
|
236
|
+
end
|
237
|
+
|
238
|
+
# By convention, Commands SHOULD return the Event, or list of Events,
|
239
|
+
# that the command published when its `perform` method was called.
|
240
|
+
case result
|
241
|
+
when Junkfood::Ceb::BaseEvent
|
242
|
+
# The single published event.
|
243
|
+
# Can assume that the command was executed.
|
244
|
+
when Array
|
245
|
+
# An array of Events published.
|
246
|
+
# Can assume that the command was executed.
|
247
|
+
when nil, false
|
248
|
+
# No data was passed back. Nothing can be assumed about the
|
249
|
+
# execution of the command.
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
OneTime - HMAC One Time Passwords
|
255
|
+
=================================
|
256
|
+
|
257
|
+
OneTime implements [RFC4226](http://tools.ietf.org/html/rfc4226) and the
|
258
|
+
[Time Based](http://tools.ietf.org/html/draft-mraihi-totp-timebased-06)
|
259
|
+
version.
|
260
|
+
|
261
|
+
View the OneTime class docs to see all the options for setting the
|
262
|
+
initial counter, time steps, and number of digits each OneTime instance.
|
263
|
+
|
264
|
+
Example:
|
265
|
+
|
266
|
+
key = '12345678901234567890'
|
267
|
+
|
268
|
+
# Using the class methods to get OTP one at a time.
|
269
|
+
puts Junkfood::OneTime.hotp(key, 0) #=> 755224
|
270
|
+
puts Junkfood::OneTime.hotp(key, 1) #=> 287082
|
271
|
+
|
272
|
+
# Changing the length of the OTP
|
273
|
+
puts Junkfood::OneTime.hotp(key, 0, :digits => 8) #=> 84755224
|
274
|
+
|
275
|
+
# Using the class methods to get multiple OTP at a time.
|
276
|
+
puts Junkfood::OneTime.hotp_multi(key, 0..1) #=> [755224, 287082]
|
277
|
+
|
278
|
+
# Create a new OTP generator starting at counter 0.
|
279
|
+
one_time = Junkfood::OneTime.new key
|
280
|
+
# Get an OTP, but don't advance the counter
|
281
|
+
puts one_time.otp #=> 755224
|
282
|
+
puts one_time.otp #=> 755224
|
283
|
+
# Get a range of OTP
|
284
|
+
puts one_time.otp :range => 2 #=> [755224, 287082]
|
285
|
+
|
286
|
+
# Get an OTP, and advance the counter
|
287
|
+
puts one_time.otp! #=> 755224
|
288
|
+
puts one_time.otp! #=> 287082
|
289
|
+
puts one_time.counter #=> 2
|
290
|
+
puts one_time.otp! :range => 2 #=> [359152, 969429]
|
291
|
+
puts one_time.counter #=> 4
|
292
|
+
|
293
|
+
# The current Time based OTP for the current epoch step.
|
294
|
+
puts one_time.totp
|
295
|
+
# A bunch of OTPs preceding and following the current epoch step OTP.
|
296
|
+
puts one_time.totp :radius => 2
|
297
|
+
|
298
|
+
# Setting the length and counter of the OTP on a OneTime instance
|
299
|
+
one_time = Junkfood::OneTime.new key, :digits => 8, :counter => 2
|
300
|
+
puts one_time.otp! #=> 37359152
|
301
|
+
puts one_time.otp! #=> 26969429
|
302
|
+
|
303
|
+
PaperclipStringIO
|
304
|
+
=================
|
305
|
+
|
306
|
+
This class allows developers to save blobs of in-memory data into
|
307
|
+
[paperclip](http://rubygems.org/gems/paperclip) enabled ActiveRecord models
|
308
|
+
without requiring the use of temporary files.
|
309
|
+
|
310
|
+
Example:
|
311
|
+
|
312
|
+
class FaxDocument < ActiveRecord::Base
|
313
|
+
has_attached_file :pdf
|
314
|
+
end
|
315
|
+
|
316
|
+
def incoming_fax_handler()
|
317
|
+
attachment = 'Blob of Faxed Data in PDF form'
|
318
|
+
fax_number = '555-1234'
|
319
|
+
|
320
|
+
fax_document = FaxDocument.create(
|
321
|
+
:caption => 'Look at this Document!',
|
322
|
+
:pdf => PaperclipStringIo.new(
|
323
|
+
attachment,
|
324
|
+
:filename => "#{fax_number}.pdf",
|
325
|
+
:content_type => 'application/pdf'))
|
326
|
+
end
|
327
|
+
|
328
|
+
|
329
|
+
Settings
|
330
|
+
========
|
331
|
+
|
332
|
+
A singleton to allow all parts of a Rails application use the same set
|
333
|
+
of settings, loaded from the same settings yaml file.
|
334
|
+
|
335
|
+
Testing
|
336
|
+
=======
|
337
|
+
This library uses [Bundler](http://gembundler.com/) for development and testing.
|
338
|
+
|
339
|
+
> bundle install
|
340
|
+
>
|
341
|
+
> rake spec
|
342
|
+
>
|
343
|
+
> rake rcov
|
344
|
+
|
345
|
+
Note on Patches/Pull Requests
|
346
|
+
=============================
|
347
|
+
* Fork the project.
|
348
|
+
* Make your feature addition or bug fix.
|
349
|
+
* Add tests for it. This is important so I don't break it in a
|
350
|
+
future version unintentionally.
|
351
|
+
* Commit, do not mess with rakefile, version, or history.
|
352
|
+
(if you want to have your own version, that is fine but bump version in a
|
353
|
+
commit by itself I can ignore when I pull)
|
354
|
+
* Send me a pull request. Bonus points for topic branches.
|
355
|
+
|
356
|
+
Authors
|
357
|
+
=======
|
358
|
+
* Benjamin Yu - <http://benjaminyu.org/>, <http://github.com/byu>
|
359
|
+
|
360
|
+
Copyright
|
361
|
+
=========
|
362
|
+
|
363
|
+
> Copyright 2009-2010 Benjamin Yu
|
364
|
+
>
|
365
|
+
> Licensed under the Apache License, Version 2.0 (the "License");
|
366
|
+
> you may not use this file except in compliance with the License.
|
367
|
+
> You may obtain a copy of the License at
|
368
|
+
>
|
369
|
+
> http://www.apache.org/licenses/LICENSE-2.0
|
370
|
+
>
|
371
|
+
> Unless required by applicable law or agreed to in writing, software
|
372
|
+
> distributed under the License is distributed on an "AS IS" BASIS,
|
373
|
+
> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
374
|
+
> See the License for the specific language governing permissions and
|
375
|
+
> limitations under the License.
|
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
gem.name = "junkfood"
|
15
|
+
gem.summary = %Q{My mesh of an all-in-one library for disjoint code.}
|
16
|
+
gem.description = %Q{My mesh of an all-in-one library for disjoint code.}
|
17
|
+
gem.email = "benjaminlyu@gmail.com"
|
18
|
+
gem.homepage = "http://github.com/byu/junkfood"
|
19
|
+
gem.authors = ["Benjamin Yu"]
|
20
|
+
|
21
|
+
gem.extra_rdoc_files << 'LICENSE'
|
22
|
+
gem.extra_rdoc_files << 'NOTICE'
|
23
|
+
gem.extra_rdoc_files << 'README.md'
|
24
|
+
|
25
|
+
gem.add_development_dependency "rspec", ">= 2.0.0.beta.19"
|
26
|
+
gem.add_development_dependency "yard", "~> 0.6.0"
|
27
|
+
gem.add_development_dependency "bundler", "~> 1.0.0"
|
28
|
+
gem.add_development_dependency "jeweler", "~> 1.5.0.pre3"
|
29
|
+
gem.add_development_dependency "rcov", ">= 0"
|
30
|
+
|
31
|
+
gem.add_runtime_dependency 'activesupport'
|
32
|
+
gem.add_runtime_dependency 'mongoid', '~> 2.0.0.beta.18'
|
33
|
+
gem.add_runtime_dependency 'wrong'
|
34
|
+
end
|
35
|
+
Jeweler::RubygemsDotOrgTasks.new
|
36
|
+
|
37
|
+
require 'rspec/core'
|
38
|
+
require 'rspec/core/rake_task'
|
39
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
40
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
41
|
+
end
|
42
|
+
|
43
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
44
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
45
|
+
spec.rcov = true
|
46
|
+
end
|
47
|
+
|
48
|
+
task :default => :spec
|
49
|
+
|
50
|
+
require 'yard'
|
51
|
+
YARD::Rake::YardocTask.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/junkfood.gemspec
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{junkfood}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Benjamin Yu"]
|
12
|
+
s.date = %q{2010-09-30}
|
13
|
+
s.description = %q{My mesh of an all-in-one library for disjoint code.}
|
14
|
+
s.email = %q{benjaminlyu@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"NOTICE",
|
18
|
+
"README.md"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".document",
|
22
|
+
".gitignore",
|
23
|
+
"Gemfile",
|
24
|
+
"Gemfile.lock",
|
25
|
+
"LICENSE",
|
26
|
+
"NOTICE",
|
27
|
+
"README.md",
|
28
|
+
"Rakefile",
|
29
|
+
"VERSION",
|
30
|
+
"junkfood.gemspec",
|
31
|
+
"lib/junkfood.rb",
|
32
|
+
"lib/junkfood/adler32.rb",
|
33
|
+
"lib/junkfood/adler32_pure.rb",
|
34
|
+
"lib/junkfood/assert.rb",
|
35
|
+
"lib/junkfood/base32.rb",
|
36
|
+
"lib/junkfood/ceb.rb",
|
37
|
+
"lib/junkfood/ceb/base_command.rb",
|
38
|
+
"lib/junkfood/ceb/base_event.rb",
|
39
|
+
"lib/junkfood/ceb/bus.rb",
|
40
|
+
"lib/junkfood/ceb/executors.rb",
|
41
|
+
"lib/junkfood/ceb/executors/command_executor.rb",
|
42
|
+
"lib/junkfood/ceb/executors/delayed_job_command_executor.rb",
|
43
|
+
"lib/junkfood/ceb/executors/event_executor.rb",
|
44
|
+
"lib/junkfood/one_time.rb",
|
45
|
+
"lib/junkfood/paperclip_string_io.rb",
|
46
|
+
"lib/junkfood/settings.rb",
|
47
|
+
"spec/.rspec",
|
48
|
+
"spec/junkfood/adler32_pure_spec.rb",
|
49
|
+
"spec/junkfood/adler32_spec.rb",
|
50
|
+
"spec/junkfood/assert_spec.rb",
|
51
|
+
"spec/junkfood/base32_spec.rb",
|
52
|
+
"spec/junkfood/ceb/base_command_spec.rb",
|
53
|
+
"spec/junkfood/ceb/base_event_spec.rb",
|
54
|
+
"spec/junkfood/ceb/bus_spec.rb",
|
55
|
+
"spec/junkfood/ceb/executors/command_executor_spec.rb",
|
56
|
+
"spec/junkfood/ceb/executors/delayed_job_command_executor_spec.rb",
|
57
|
+
"spec/junkfood/ceb/executors/event_executor_spec.rb",
|
58
|
+
"spec/junkfood/one_time_spec.rb",
|
59
|
+
"spec/junkfood/paperclip_string_io_spec.rb",
|
60
|
+
"spec/junkfood/settings_spec.rb",
|
61
|
+
"spec/junkfood_spec.rb",
|
62
|
+
"spec/spec_helper.rb"
|
63
|
+
]
|
64
|
+
s.homepage = %q{http://github.com/byu/junkfood}
|
65
|
+
s.require_paths = ["lib"]
|
66
|
+
s.rubygems_version = %q{1.3.7}
|
67
|
+
s.summary = %q{My mesh of an all-in-one library for disjoint code.}
|
68
|
+
s.test_files = [
|
69
|
+
"spec/junkfood/adler32_pure_spec.rb",
|
70
|
+
"spec/junkfood/adler32_spec.rb",
|
71
|
+
"spec/junkfood/assert_spec.rb",
|
72
|
+
"spec/junkfood/base32_spec.rb",
|
73
|
+
"spec/junkfood/ceb/base_command_spec.rb",
|
74
|
+
"spec/junkfood/ceb/base_event_spec.rb",
|
75
|
+
"spec/junkfood/ceb/bus_spec.rb",
|
76
|
+
"spec/junkfood/ceb/executors/command_executor_spec.rb",
|
77
|
+
"spec/junkfood/ceb/executors/delayed_job_command_executor_spec.rb",
|
78
|
+
"spec/junkfood/ceb/executors/event_executor_spec.rb",
|
79
|
+
"spec/junkfood/one_time_spec.rb",
|
80
|
+
"spec/junkfood/paperclip_string_io_spec.rb",
|
81
|
+
"spec/junkfood/settings_spec.rb",
|
82
|
+
"spec/junkfood_spec.rb",
|
83
|
+
"spec/spec_helper.rb"
|
84
|
+
]
|
85
|
+
|
86
|
+
if s.respond_to? :specification_version then
|
87
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
88
|
+
s.specification_version = 3
|
89
|
+
|
90
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
91
|
+
s.add_development_dependency(%q<bluecloth>, [">= 0"])
|
92
|
+
s.add_development_dependency(%q<rspec>, [">= 2.0.0.beta.22"])
|
93
|
+
s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
|
94
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
95
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
|
96
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
97
|
+
s.add_development_dependency(%q<activesupport>, [">= 0"])
|
98
|
+
s.add_development_dependency(%q<mongoid>, ["~> 2.0.0.beta.18"])
|
99
|
+
s.add_development_dependency(%q<wrong>, [">= 0"])
|
100
|
+
s.add_development_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
|
101
|
+
s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
|
102
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
103
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
|
104
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
105
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
106
|
+
s.add_runtime_dependency(%q<mongoid>, ["~> 2.0.0.beta.18"])
|
107
|
+
s.add_runtime_dependency(%q<wrong>, [">= 0"])
|
108
|
+
else
|
109
|
+
s.add_dependency(%q<bluecloth>, [">= 0"])
|
110
|
+
s.add_dependency(%q<rspec>, [">= 2.0.0.beta.22"])
|
111
|
+
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
112
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
113
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
|
114
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
115
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
116
|
+
s.add_dependency(%q<mongoid>, ["~> 2.0.0.beta.18"])
|
117
|
+
s.add_dependency(%q<wrong>, [">= 0"])
|
118
|
+
s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
|
119
|
+
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
120
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
121
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
|
122
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
123
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
124
|
+
s.add_dependency(%q<mongoid>, ["~> 2.0.0.beta.18"])
|
125
|
+
s.add_dependency(%q<wrong>, [">= 0"])
|
126
|
+
end
|
127
|
+
else
|
128
|
+
s.add_dependency(%q<bluecloth>, [">= 0"])
|
129
|
+
s.add_dependency(%q<rspec>, [">= 2.0.0.beta.22"])
|
130
|
+
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
131
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
132
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
|
133
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
134
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
135
|
+
s.add_dependency(%q<mongoid>, ["~> 2.0.0.beta.18"])
|
136
|
+
s.add_dependency(%q<wrong>, [">= 0"])
|
137
|
+
s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
|
138
|
+
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
139
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
140
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
|
141
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
142
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
143
|
+
s.add_dependency(%q<mongoid>, ["~> 2.0.0.beta.18"])
|
144
|
+
s.add_dependency(%q<wrong>, [">= 0"])
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2009 Benjamin Yu <http://benjaminyu.org/>
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require 'zlib'
|
17
|
+
|
18
|
+
module Junkfood
|
19
|
+
|
20
|
+
##
|
21
|
+
# A Ruby implementation of the Adler-32 checksum algorithm,
|
22
|
+
# which uses Ruby's own Zlib.adler32 class method.
|
23
|
+
#
|
24
|
+
# This Ruby implementation is a port of the Python adler32
|
25
|
+
# implementation found in the pysync project. The Python reference
|
26
|
+
# implementation, itself, was a port from zlib's adler32.c file.
|
27
|
+
#
|
28
|
+
# @see http://zlib.net/
|
29
|
+
# @see http://freshmeat.net/projects/pysync/
|
30
|
+
#
|
31
|
+
class Adler32
|
32
|
+
|
33
|
+
# largest prime smaller than 65536
|
34
|
+
BASE = 65521
|
35
|
+
# largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
|
36
|
+
NMAX = 5552
|
37
|
+
# default initial s1 offset
|
38
|
+
OFFS = 1
|
39
|
+
|
40
|
+
##
|
41
|
+
# @param data (String) initial block of data to digest.
|
42
|
+
#
|
43
|
+
def initialize(data='')
|
44
|
+
value = Zlib.adler32(data, OFFS)
|
45
|
+
@s2, @s1 = (value >> 16) & 0xffff, value & 0xffff
|
46
|
+
@count = data.length
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Adds another block of data to digest.
|
51
|
+
#
|
52
|
+
# @param data (String) block of data to digest.
|
53
|
+
# @return (Fixnum) the updated digest.
|
54
|
+
#
|
55
|
+
def update(data)
|
56
|
+
value = Zlib.adler32(data, (@s2 << 16) | @s1)
|
57
|
+
@s2, @s1 = (value >> 16) & 0xffff, value & 0xffff
|
58
|
+
@count = @count + data.length
|
59
|
+
return self.digest
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# @param x1 (Byte)
|
64
|
+
# @param xn (Byte)
|
65
|
+
# @return (Fixnum) the updated digest.
|
66
|
+
#
|
67
|
+
def rotate(x1, xn)
|
68
|
+
@s1 = (@s1 - x1 + xn) % BASE
|
69
|
+
@s2 = (@s2 - (@count * x1) + @s1 - OFFS) % BASE
|
70
|
+
return self.digest
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# @param b (Byte)
|
75
|
+
# @return (Fixnum) the updated digest.
|
76
|
+
#
|
77
|
+
def rollin(b)
|
78
|
+
@s1 = (@s1 + b) % BASE
|
79
|
+
@s2 = (@s2 + @s1) % BASE
|
80
|
+
@count = @count + 1
|
81
|
+
return self.digest
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# @param b (Byte)
|
86
|
+
# @return (Fixnum) the updated digest.
|
87
|
+
#
|
88
|
+
def rollout(b)
|
89
|
+
@s1 = (@s1 - b) % BASE
|
90
|
+
@s2 = (@s2 - @count * b) % BASE
|
91
|
+
@count = @count - 1
|
92
|
+
return self.digest
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# @return (Fixnum) the current Adler32 digest value.
|
97
|
+
#
|
98
|
+
def digest
|
99
|
+
return (@s2 << 16) | @s1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|