Skip to content
This repository
Browse code

When doing a uncompress, return error if uncompression fails. For now…

…, assume that it fails because of invalid data.
  • Loading branch information...
commit bab290ead24dbc06693a7276f934e30c245235d2 1 parent 9f56b33
David Björklund authored April 21, 2011
67  binding.cc
@@ -27,13 +27,37 @@
27 27
 
28 28
 namespace nodesnappy {
29 29
 
30  
-// CompressUncompressBinding
  30
+const std::string SnappyErrors::kInvalidInput = "Invalid input";
  31
+
  32
+// Base
  33
+// PROTECTED
  34
+inline void Base::CallCallback(const v8::Handle<v8::Function>& callback,
  35
+                                  const v8::Handle<v8::Value>& err,
  36
+                                  const v8::Handle<v8::Value>& res) {
  37
+  v8::Handle<v8::Value> argv[2] = {err, res};
  38
+  callback->Call(v8::Context::GetCurrent()->Global(), 2, argv);
  39
+}
  40
+
  41
+inline void Base::CallErrCallback(const v8::Handle<v8::Function>& callback,
  42
+                                  const std::string& str) {
  43
+  v8::Handle<v8::Value> err =
  44
+    v8::Exception::Error(v8::String::New(str.data(), str.length()));
  45
+  v8::Handle<v8::Value> res = v8::Local<v8::Value>::New(v8::Null());
  46
+  CallCallback(callback, err, res);
  47
+}
  48
+
  49
+// CompressUncompressBase
31 50
 // PROTECTED
32 51
 int CompressUncompressBase::After(eio_req *req) {
33 52
   v8::HandleScope scope;
34 53
   SnappyRequest<std::string>* snappy_request =
35 54
     static_cast<SnappyRequest<std::string>*>(req->data);
36  
-  CallCallback(snappy_request->callback, snappy_request->result);
  55
+  if (snappy_request->err != NULL) {
  56
+    CallErrCallback(snappy_request->callback, *snappy_request->err);
  57
+  } else {
  58
+    CallOkCallback(snappy_request->callback, snappy_request->result);
  59
+  }
  60
+
37 61
   ev_unref(EV_DEFAULT_UC);
38 62
   snappy_request->callback.Dispose();
39 63
   delete snappy_request;
@@ -41,13 +65,12 @@ int CompressUncompressBase::After(eio_req *req) {
41 65
 }
42 66
 
43 67
 inline void
44  
-CompressUncompressBase::CallCallback(const v8::Handle<v8::Function>& callback,
45  
-                                      const std::string& str) {
46  
-  v8::Handle<v8::Object> buffer =
  68
+CompressUncompressBase::CallOkCallback(const v8::Handle<v8::Function>& callback,
  69
+                                       const std::string& str) {
  70
+  v8::Handle<v8::Value> err = v8::Local<v8::Value>::New(v8::Null());
  71
+  v8::Handle<v8::Value> res =
47 72
                    node::Buffer::New(v8::String::New(str.data(), str.length()));
48  
-  v8::Handle<v8::Value> argv[2] = {v8::Local<v8::Value>::New(v8::Null()),
49  
-                                   buffer};
50  
-  callback->Call(v8::Context::GetCurrent()->Global(), 2, argv);
  73
+  CallCallback(callback, err, res);
51 74
 }
52 75
 
53 76
 // CompressBinding
@@ -66,7 +89,7 @@ v8::Handle<v8::Value> CompressBinding::Sync(const v8::Arguments& args) {
66 89
   v8::String::Utf8Value data(args[0]->ToString());
67 90
   std::string dst;
68 91
   snappy::Compress(*data, data.length(), &dst);
69  
-  CallCallback(v8::Local<v8::Function>::Cast(args[1]), dst);
  92
+  CallOkCallback(v8::Local<v8::Function>::Cast(args[1]), dst);
70 93
   return scope.Close(v8::Undefined());
71 94
 }
72 95
 
@@ -96,8 +119,13 @@ v8::Handle<v8::Value> UncompressBinding::Sync(const v8::Arguments& args) {
96 119
   v8::HandleScope scope;
97 120
   std::string dst;
98 121
   v8::String::Utf8Value data(args[0]->ToString());
99  
-  snappy::Uncompress(*data, data.length(), &dst);
100  
-  CallCallback(v8::Local<v8::Function>::Cast(args[1]), dst);
  122
+  bool ok = snappy::Uncompress(*data, data.length(), &dst);
  123
+  if (ok) {
  124
+    CallOkCallback(v8::Local<v8::Function>::Cast(args[1]), dst);
  125
+  } else {
  126
+    CallErrCallback(v8::Local<v8::Function>::Cast(args[1]),
  127
+                    SnappyErrors::kInvalidInput);
  128
+  }
101 129
   return scope.Close(v8::Undefined());
102 130
 }
103 131
 
@@ -107,8 +135,12 @@ int UncompressBinding::AsyncOperation(eio_req *req) {
107 135
     static_cast<SnappyRequest<std::string>*>(req->data);
108 136
   std::string dst;
109 137
   std::string* input = &snappy_request->input;
110  
-  snappy::Uncompress(input->data(), input->length(), &dst);
111  
-  snappy_request->result = dst;
  138
+  bool ok = snappy::Uncompress(input->data(), input->length(), &dst);
  139
+  if (ok) {
  140
+    snappy_request->result = dst;
  141
+  } else {
  142
+    snappy_request->err = &SnappyErrors::kInvalidInput;
  143
+  }
112 144
   return 0;
113 145
 }
114 146
 
@@ -131,7 +163,7 @@ IsValidCompressedBinding::Sync(const v8::Arguments& args) {
131 163
   std::string dst;
132 164
   v8::String::Utf8Value data(args[0]->ToString());
133 165
   bool valid = snappy::IsValidCompressedBuffer(*data, data.length());
134  
-  CallCallback(v8::Local<v8::Function>::Cast(args[1]), valid);
  166
+  CallOkCallback(v8::Local<v8::Function>::Cast(args[1]), valid);
135 167
   return scope.Close(v8::Undefined());
136 168
 }
137 169
 
@@ -140,7 +172,7 @@ int IsValidCompressedBinding::After(eio_req *req) {
140 172
   v8::HandleScope scope;
141 173
   SnappyRequest<bool>* snappy_request =
142 174
     static_cast<SnappyRequest<bool>*>(req->data);
143  
-  CallCallback(snappy_request->callback, snappy_request->result);
  175
+  CallOkCallback(snappy_request->callback, snappy_request->result);
144 176
   ev_unref(EV_DEFAULT_UC);
145 177
   snappy_request->callback.Dispose();
146 178
   delete snappy_request;
@@ -156,8 +188,9 @@ int IsValidCompressedBinding::AsyncOperation(eio_req *req) {
156 188
 }
157 189
 
158 190
 inline void
159  
-IsValidCompressedBinding::CallCallback(const v8::Handle<v8::Function>& callback,
160  
-                                      const bool data) {
  191
+IsValidCompressedBinding::CallOkCallback(
  192
+    const v8::Handle<v8::Function>& callback,
  193
+    const bool data) {
161 194
   v8::Handle<v8::Value> argv[2] = {v8::Local<v8::Value>::New(v8::Null()),
162 195
                              v8::Local<v8::Value>::New(v8::Boolean::New(data))};
163 196
   callback->Call(v8::Context::GetCurrent()->Global(), 2, argv);
49  binding.h
@@ -33,24 +33,57 @@ template<class T> struct SnappyRequest {
33 33
   std::string input;
34 34
   T result;
35 35
   v8::Persistent<v8::Function> callback;
  36
+  const std::string* err;
36 37
   inline SnappyRequest(const v8::Arguments& args) {
37 38
     v8::String::Utf8Value data(args[0]->ToString());
38 39
     input = std::string(*data, data.length());
39 40
     v8::Local<v8::Function> local = v8::Local<v8::Function>::Cast(args[1]);
40 41
     callback = v8::Persistent<v8::Function>::New(local);
  42
+    err = NULL;
41 43
   }
42 44
 };
43 45
 
44 46
 /*
  47
+ * Error messages.
  48
+ */
  49
+struct SnappyErrors {
  50
+  static const std::string kInvalidInput;
  51
+};
  52
+
  53
+/*
  54
+ * Base class for all bindings.
  55
+ */
  56
+class Base {
  57
+ protected:
  58
+  /*
  59
+   * Calls the specifed callback when something has gone wrong.
  60
+   * Converts the specifed string to an Error as first argument and use null as
  61
+   * the second argument.
  62
+   */
  63
+  static void CallErrCallback(const v8::Handle<v8::Function>&,
  64
+                              const std::string&);
  65
+  /*
  66
+   * Call the specifed callback with err and res as arguments.
  67
+   */
  68
+  static void CallCallback(const v8::Handle<v8::Function>& callback,
  69
+                           const v8::Handle<v8::Value>& err,
  70
+                           const v8::Handle<v8::Value>& res);
  71
+};
  72
+
  73
+/*
45 74
  * Base class for both compress and uncompress including shared methods
46 75
  */
47  
-class CompressUncompressBase {
  76
+class CompressUncompressBase : protected Base {
48 77
  protected:
  78
+  /* Method run after the async operation */
49 79
   static int After(eio_req *req);
50  
-  /* Call the specifed callback.
  80
+  /* 
  81
+   * Call the specifed callback when everything has gone well.
51 82
    * Use null as first argument and use the specifed string (converted to a
52  
-   * Buffer) as second argument.*/
53  
-  static void CallCallback(const v8::Handle<v8::Function>&, const std::string&);
  83
+   * Buffer) as second argument.
  84
+   */
  85
+  static void CallOkCallback(const v8::Handle<v8::Function>&,
  86
+                             const std::string&);
54 87
 };
55 88
 
56 89
 /* 
@@ -65,6 +98,7 @@ class CompressBinding : CompressUncompressBase {
65 98
   static v8::Handle<v8::Value> Sync(const v8::Arguments& args);
66 99
 
67 100
  private:
  101
+
68 102
   static int AsyncOperation(eio_req *req);
69 103
 };
70 104
 
@@ -97,7 +131,12 @@ class IsValidCompressedBinding {
97 131
  private:
98 132
   static int After(eio_req *req);
99 133
   static int AsyncOperation(eio_req *req);
100  
-  static void CallCallback(const v8::Handle<v8::Function>&, const bool);
  134
+  /* 
  135
+   * Call the specifed callback when everything has gone well.
  136
+   * Use null as first argument and use the specifed bool (converted to a
  137
+   * Boolean) as second argument.
  138
+   */
  139
+  static void CallOkCallback(const v8::Handle<v8::Function>&, const bool);
101 140
 };
102 141
 
103 142
 }  // namespace nodesnappy
6  snappy.coffee
@@ -52,12 +52,14 @@ exports.isValidCompressedSync = (input, callback) ->
52 52
 # de-/uncompress
53 53
 exports.uncompress = (compressed, callback, parse = @parsers.raw) ->
54 54
   binding.uncompress(compressed, (err, data) ->
55  
-    callback(err, parse(data))
  55
+    data = parse(data) if data?
  56
+    callback(err, data)
56 57
   )
57 58
 exports.decompress = exports.uncompress
58 59
 
59 60
 exports.uncompressSync = (compressed, callback, parse = @parsers.raw) ->
60 61
   binding.uncompressSync(compressed, (err, data) ->
61  
-    callback(err, parse(data))
  62
+    data = parse(data) if data?
  63
+    callback(err, data)
62 64
   )
63 65
 exports.decompressSync = exports.uncompressSync
54  test.coffee
@@ -24,9 +24,11 @@ vows = require 'vows'
24 24
 assert = require 'assert'
25 25
 snappy = require './snappy'
26 26
 
27  
-assert.isBuffer = (buf)->
  27
+assert.isBuffer = (buf) ->
28 28
   assert.instanceOf buf, Buffer
29 29
 
  30
+assert.isError = (err) ->
  31
+  assert.instanceOf err, Error
30 32
 string = "foo foo foo  Fasfa daos asd foo foo foo asdasf bar bar aarr"
31 33
 buffer = new Buffer(string)
32 34
 json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
@@ -35,8 +37,8 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
35 37
 ["", "Sync"].forEach (sync)->
36 38
   title = if sync is "" then "asyncronous" else "synchronous"
37 39
   vows.describe("snappy (#{title} versions)").addBatch(
38  
-    "A buffer":
39  
-      "compressed":
  40
+    "compress":
  41
+      "Buffer":
40 42
         topic: () -> snappy["compress#{sync}"](buffer, @callback)
41 43
         'should not have errors': (err, compressed) ->
42 44
           assert.isNull err
@@ -44,7 +46,7 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
44 46
         'should result in a buffer': (err, compressed) ->
45 47
           assert.isBuffer compressed
46 48
 
47  
-        'and tested if valid':
  49
+        'and isValidCompressed':
48 50
           topic: (compressed) -> snappy["isValidCompressed#{sync}"](compressed, @callback)
49 51
           'should not have errors': (err, result) ->
50 52
             assert.isNull err
@@ -52,7 +54,7 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
52 54
           'should result in true': (err, result) ->
53 55
             assert.isTrue result
54 56
 
55  
-        'and decompressed with string-parser':
  57
+        'and decompress (string-parser)':
56 58
           topic: (compressed) -> snappy["decompress#{sync}"](compressed, @callback, snappy.parsers.string)
57 59
           'should not have errors': (err, result) ->
58 60
             assert.isNull err
@@ -63,7 +65,7 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
63 65
           'should equal the original when parsed': (err, result) ->
64 66
             assert.strictEqual result, buffer.toString("utf8")
65 67
 
66  
-        'and decompressed without any parser':
  68
+        'and decompress (no parser)':
67 69
           topic: (compressed) -> snappy["decompress#{sync}"](compressed, @callback)
68 70
           'should not have errors': (err, result) ->
69 71
             assert.isNull err
@@ -74,8 +76,7 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
74 76
           'should equal the original': (err, result) ->
75 77
             assert.strictEqual result.toString("utf8"), buffer.toString("utf8")
76 78
 
77  
-    "A json-object":
78  
-      "compressed":
  79
+      "json":
79 80
         topic: () -> snappy["compress#{sync}"](json, @callback)
80 81
         'should not have errors': (err, compressed) ->
81 82
           assert.isNull err
@@ -83,7 +84,7 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
83 84
         'should result in a buffer': (err, compressed) ->
84 85
           assert.isBuffer compressed
85 86
 
86  
-        'and tested if valid':
  87
+        'and isValidCompressed':
87 88
           topic: (compressed) -> snappy["isValidCompressed#{sync}"](compressed, @callback)
88 89
           'should not have errors': (err, result) ->
89 90
             assert.isNull err
@@ -91,7 +92,7 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
91 92
           'should result in true': (err, result) ->
92 93
             assert.isTrue result
93 94
 
94  
-        'and decompressed with json-parser':
  95
+        'and decompress (json-parser)':
95 96
           topic: (compressed) -> snappy["decompress#{sync}"](compressed, @callback, snappy.parsers.json)
96 97
           'should not have errors': (err, result) ->
97 98
             assert.isNull err
@@ -103,7 +104,7 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
103 104
           'should equal the original': (err, result) ->
104 105
             assert.deepEqual result, json
105 106
 
106  
-        'and decompressed with string-parser':
  107
+        'and decompress (string-parser)':
107 108
           topic: (compressed) -> snappy["decompress#{sync}"](compressed, @callback, snappy.parsers.string)
108 109
           'should not have errors': (err, result) ->
109 110
             assert.isNull err
@@ -114,7 +115,7 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
114 115
           'should equal the original when parsed': (err, result) ->
115 116
             assert.deepEqual JSON.parse(result), json
116 117
 
117  
-        'and decompressed without any parser':
  118
+        'and decompress (no parser)':
118 119
           topic: (compressed) -> snappy["decompress#{sync}"](compressed, @callback)
119 120
           'should not have errors': (err, result) ->
120 121
             assert.isNull err
@@ -125,8 +126,7 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
125 126
           'should equal the original when parsed': (err, result) ->
126 127
             assert.deepEqual JSON.parse(result), json
127 128
 
128  
-    "A string":
129  
-      "compressed":
  129
+      "string":
130 130
         topic: () -> snappy["compress#{sync}"](string, @callback)
131 131
         'should not have errors': (err, compressed) ->
132 132
           assert.isNull err
@@ -134,7 +134,7 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
134 134
         'should result in a buffer': (err, compressed) ->
135 135
           assert.isBuffer compressed
136 136
 
137  
-        'and tested if valid':
  137
+        'and isValidCompressed':
138 138
           topic: (compressed) -> snappy["isValidCompressed#{sync}"](compressed, @callback)
139 139
           'should not have errors': (err, result) ->
140 140
             assert.isNull err
@@ -142,7 +142,7 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
142 142
           'should result in true': (err, result) ->
143 143
             assert.isTrue result
144 144
 
145  
-        'and decompressed with string-parser':
  145
+        'and decompress (string-parser)':
146 146
           topic: (compressed) -> snappy["decompress#{sync}"](compressed, @callback, snappy.parsers.string)
147 147
           'should not have errors': (err, result) ->
148 148
             assert.isNull err
@@ -153,16 +153,34 @@ json = {"foo" : "bar", "fou" : 0, "shou" : "ho ho", "what?" : ["hey", "you"]}
153 153
           'should equal the original': (err, result) ->
154 154
             assert.strictEqual result, string
155 155
 
156  
-        'and decompressed without any parser':
  156
+        'and decompress (no parser)':
157 157
           topic: (compressed) -> snappy["decompress#{sync}"](compressed, @callback)
158 158
           'should not have errors': (err, result) ->
159 159
             assert.isNull err
160 160
           
161  
-          'should result in a buffer': (err, result) ->
  161
+          'should result in a Buffer': (err, result) ->
162 162
             assert.isBuffer result
163 163
 
164 164
           'should equal the original when parsed': (err, result) ->
165 165
             string2 = result.toString("utf8")
166 166
             assert.strictEqual string2, string
167 167
 
  168
+    "uncompress":
  169
+      "buffer (invalid)":
  170
+        topic: () -> snappy["decompress#{sync}"](buffer, @callback, snappy.parsers.string)
  171
+        'should have error': (err, result) ->
  172
+          assert.isError err
  173
+        
  174
+        'should have "Invalid input"-error': (err, result) ->
  175
+          assert.strictEqual err.message ,"Invalid input"
  176
+
  177
+    "isValidCompressed":
  178
+      "buffer (invalid)":
  179
+        topic: () -> snappy["isValidCompressed#{sync}"](buffer, @callback)
  180
+        'should not have errors': (err, result) ->
  181
+          assert.isNull err
  182
+
  183
+        'should result in false': (err, result) ->
  184
+          assert.isFalse result
  185
+      
168 186
   ).export(module)

0 notes on commit bab290e

Please sign in to comment.
Something went wrong with that request. Please try again.