Asylo
statusor.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2017 Asylo authors
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef ASYLO_UTIL_STATUSOR_H_
20 #define ASYLO_UTIL_STATUSOR_H_
21 
22 #include <type_traits>
23 #include <utility>
24 
25 #include "absl/base/attributes.h"
26 #include "absl/base/config.h"
27 #include "absl/meta/type_traits.h"
28 #include "absl/status/status.h"
29 #include "absl/status/statusor.h"
30 #include "asylo/util/logging.h"
31 #include "asylo/util/cleanup.h"
32 #include "asylo/util/status.h"
33 #include "asylo/util/status_error_space.h"
34 
35 namespace asylo {
36 
37 #ifdef NDEBUG
38 ABSL_CONST_INIT extern const char kValueMoveConstructorMsg[];
39 ABSL_CONST_INIT extern const char kValueMoveAssignmentMsg[];
40 ABSL_CONST_INIT extern const char kValueOrDieMovedMsg[];
41 ABSL_CONST_INIT extern const char kStatusMoveConstructorMsg[];
42 ABSL_CONST_INIT extern const char kStatusMoveAssignmentMsg[];
43 #else
44 ABSL_CONST_INIT extern const char kValueMoveConstructorMsg[];
45 ABSL_CONST_INIT extern const char kValueMoveAssignmentMsg[];
46 ABSL_CONST_INIT extern const char kValueOrDieMovedMsg[];
47 ABSL_CONST_INIT extern const char kStatusMoveConstructorMsg[];
48 ABSL_CONST_INIT extern const char kStatusMoveAssignmentMsg[];
49 #endif
50 
51 /// A class for representing either a usable value, or an error.
52 ///
53 /// A StatusOr object either contains a value of type `T` or a Status object
54 /// explaining why such a value is not present. The type `T` must be
55 /// copy-constructible and/or move-constructible.
56 ///
57 /// The state of a StatusOr object may be determined by calling ok() or
58 /// status(). The ok() method returns true if the object contains a valid value.
59 /// The status() method returns the internal Status object. A StatusOr object
60 /// that contains a valid value will return an OK Status for a call to status().
61 ///
62 /// A value of type `T` may be extracted by dereferencing an OK StatusOr object,
63 /// either with operator*() or operator->(). These operators should only be
64 /// called if a call to ok() returns true. Sample usage:
65 ///
66 /// ```
67 /// asylo::StatusOr<Foo> result = CalculateFoo();
68 /// if (result.ok()) {
69 /// Foo foo = *result;
70 /// foo.DoSomethingCool();
71 /// } else {
72 /// LOG(ERROR) << result.status();
73 /// }
74 /// ```
75 ///
76 /// Or more concisely:
77 ///
78 /// ```
79 /// asylo::StatusOr<Foo> result = CalculateFoo();
80 /// if (result.ok()) {
81 /// result->DoSomethingCool();
82 /// } else {
83 /// LOG(ERROR) << result.status();
84 /// }
85 /// ```
86 ///
87 /// If `T` is a move-only type, like `std::unique_ptr<>`, then the value should
88 /// only be extracted after invoking `std::move()` on the StatusOr object.
89 /// Sample usage:
90 ///
91 /// ```
92 /// asylo::StatusOr<std::unique_ptr<Foo>> result = CalculateFoo();
93 /// if (result.ok()) {
94 /// std::unique_ptr<Foo> foo = *std::move(result);
95 /// foo->DoSomethingCool();
96 /// } else {
97 /// LOG(ERROR) << result.status();
98 /// }
99 /// ```
100 ///
101 /// If exceptions are enabled, callers can alternatively use the `value()`
102 /// method to extract the contents of a StatusOr. Calls to `value()` throw
103 /// `absl::BadStatusOrAccess` if the StatusOr is not OK. Sample usage:
104 ///
105 /// ```
106 /// asylo::StatusOr<Foo> result = CalculateFoo();
107 /// try {
108 /// result.value().DoSomethingCool();
109 /// } catch (const absl::BadStatusOrAccess &bad_access) {
110 /// LOG(ERROR) << bad_access.status();
111 /// }
112 /// ```
113 ///
114 /// If exceptions are disabled, then calls to `value()` on a non-OK StatusOr
115 /// will abort the program.
116 ///
117 /// StatusOr is provided for the convenience of implementing functions that
118 /// return some value but may fail during execution. For instance, consider a
119 /// function with the following signature:
120 ///
121 /// ```
122 /// asylo::Status CalculateFoo(int *output);
123 /// ```
124 ///
125 /// This function may instead be written as:
126 ///
127 /// ```
128 /// asylo::StatusOr<int> CalculateFoo();
129 /// ```
130 template <class T>
131 class StatusOr {
132  template <typename U>
133  friend class StatusOr;
134 
135  // A traits class that determines whether a type U is implicitly convertible
136  // from a type V. If it is convertible, then the `value` member of this class
137  // is statically set to true, otherwise it is statically set to false.
138  template <class U, typename V>
139  struct is_implicitly_constructible
140  : absl::conjunction<std::is_constructible<U, V>,
141  std::is_convertible<V, U> > {};
142 
143  public:
144  /// An alias for T. Useful for generic programming.
145  using value_type = T;
146 
147  /// Constructs a StatusOr object that contains a non-OK status.
148  /// The non-OK status has an error code of -1. This is a non-standard POSIX
149  /// error code and is used in this context to indicate an unknown error.
150  ///
151  /// This constructor is marked `explicit` to prevent attempts to `return {}`
152  /// from a function with a return type of, for example,
153  /// `StatusOr<std::vector<int>>`. While `return {}` seems like it would return
154  /// an empty vector, it will actually invoke the default constructor of
155  /// StatusOr.
156  explicit StatusOr()
157  : variant_(Status(error::GoogleError::UNKNOWN, "Unknown error")),
158  has_value_(false) {}
159 
160  ~StatusOr() {
161  if (has_value_) {
162  variant_.value_.~T();
163  } else {
164  variant_.status_.~Status();
165  }
166  }
167 
168  /// Constructs a StatusOr object with the given non-OK Status object. The
169  /// given `status` must not be an OK status, otherwise this constructor will
170  /// abort.
171  ///
172  /// This constructor is not declared explicit so that a function with a return
173  /// type of `StatusOr<T>` can return a Status object, and the status will be
174  /// implicitly converted to the appropriate return type as a matter of
175  /// convenience.
176  ///
177  /// \param status The non-OK Status object to initalize to.
178  StatusOr(const Status &status)
179  : variant_(status), has_value_(false) {
180  if (status.ok()) {
181  LOG(FATAL) << "Cannot instantiate StatusOr with absl::OkStatus()";
182  }
183  }
184 
185  /// Constructs a StatusOr object with the given non-OK `absl::Status` object.
186  /// All calls to value() on this object will throw an exception or cause the
187  /// program to abort. The given `status` must not be an OK status, otherwise
188  /// this constructor will cause an abort.
189  ///
190  /// This constructor is not declared explicit so that a function with a return
191  /// type of `StatusOr<T>` can return an `absl::Status` object, and the status
192  /// will be implicitly converted to the appropriate return type as a matter of
193  /// convenience.
194  ///
195  /// \param status The non-OK `absl::Status` object to initalize to.
196  StatusOr(const absl::Status &status)
197  : variant_(Status(status)), has_value_(false) {
198  if (status.ok()) {
199  LOG(FATAL) << "Cannot instantiate StatusOr with absl::OkStatus()";
200  }
201  }
202 
203  /// Constructs a StatusOr object that contains `value`. The resulting object
204  /// is considered to have an OK status. The wrapped element can be accessed
205  /// by dereferencing or with value().
206  ///
207  /// This constructor is made implicit so that a function with a return type of
208  /// `StatusOr<T>` can return an object of type `U &&`, implicitly converting
209  /// it to a `StatusOr<T>` object.
210  ///
211  /// Note that `T` must be implicitly constructible from `U`, and `U` must not
212  /// be a (cv-qualified) Status or Status-reference type. Due to C++
213  /// reference-collapsing rules and perfect-forwarding semantics, this
214  /// constructor matches invocations that pass `value` either as a const
215  /// reference or as an rvalue reference. Since StatusOr needs to work for both
216  /// reference and rvalue-reference types, the constructor uses perfect
217  /// forwarding to avoid invalidating arguments that were passed by reference.
218  /// See http://thbecker.net/articles/rvalue_references/section_08.html for
219  /// additional details.
220  ///
221  /// \param value The value to initialize to.
222  template <typename U,
223  typename E = typename std::enable_if<
224  is_implicitly_constructible<T, U>::value &&
225  !std::is_same<typename std::remove_reference<
226  typename std::remove_cv<U>::type>::type,
227  Status>::value &&
228  !std::is_same<typename std::remove_reference<
229  typename std::remove_cv<U>::type>::type,
230  absl::Status>::value>::type>
231  StatusOr(U &&value) : variant_(std::forward<U>(value)), has_value_(true) {}
232 
233  /// Copy constructor.
234  ///
235  /// This constructor needs to be explicitly defined because the presence of
236  /// the move-assignment operator deletes the default copy constructor. In such
237  /// a scenario, since the deleted copy constructor has stricter binding rules
238  /// than the templated copy constructor, the templated constructor cannot act
239  /// as a copy constructor, and any attempt to copy-construct a `StatusOr`
240  /// object results in a compilation error.
241  ///
242  /// \param other The value to copy from.
243  StatusOr(const StatusOr &other) : has_value_(other.has_value_) {
244  if (has_value_) {
245  new (&variant_) variant(other.variant_.value_);
246  } else {
247  new (&variant_) variant(other.variant_.status_);
248  }
249  }
250 
251  /// Templatized constructor that constructs a `StatusOr<T>` from a const
252  /// reference to a `StatusOr<U>`.
253  ///
254  /// `T` must be implicitly constructible from `const U &`.
255  ///
256  /// \param other The value to copy from.
257  template <typename U,
258  typename E = typename std::enable_if<
259  is_implicitly_constructible<T, const U &>::value>::type>
260  StatusOr(const StatusOr<U> &other)
261  : has_value_(other.has_value_) {
262  if (has_value_) {
263  new (&variant_) variant(other.variant_.value_);
264  } else {
265  new (&variant_) variant(other.variant_.status_);
266  }
267  }
268 
269  /// Templatized constructor that constructs a `StatusOr<T>` from a const
270  /// reference to an `absl::StatusOr<U>`.
271  ///
272  /// `T` must be implicitly constructible from `const U &`.
273  ///
274  /// \param other The value to copy from.
275  template <typename U,
276  typename E = typename std::enable_if<
277  is_implicitly_constructible<T, const U &>::value>::type>
278  StatusOr(const absl::StatusOr<U> &other)
279  : has_value_(other.ok()) {
280  if (has_value_) {
281  new (&variant_) variant(*other);
282  } else {
283  new (&variant_) variant(other.status());
284  }
285  }
286 
287  /// Copy-assignment operator.
288  ///
289  /// \param other The StatusOr object to copy.
290  StatusOr &operator=(const StatusOr &other) {
291  // Check for self-assignment.
292  if (this == &other) {
293  return *this;
294  }
295 
296  // Construct the variant object using the variant object of the source.
297  if (other.has_value_) {
298  AssignValue(other.variant_.value_);
299  } else {
300  AssignStatus(other.variant_.status_);
301  }
302  return *this;
303  }
304 
305  /// Templatized constructor which constructs a `StatusOr<T>` by moving the
306  /// contents of a `StatusOr<U>`. `T` must be implicitly constructible from `U
307  /// &&`.
308  ///
309  /// Sets `other` to a valid but unspecified state.
310  ///
311  /// \param other The StatusOr object to move from.
312  template <typename U, typename E = typename std::enable_if<
313  is_implicitly_constructible<T, U &&>::value>::type>
314  StatusOr(StatusOr<U> &&other) : has_value_(other.has_value_) {
315  if (has_value_) {
316  new (&variant_) variant(std::move(other.variant_.value_));
317  other.OverwriteValueWithStatus(
318  Status(error::StatusError::MOVED, kValueMoveConstructorMsg));
319  } else {
320  new (&variant_) variant(std::move(other.variant_.status_));
321 #ifndef NDEBUG
322  // The other.variant_.status_ gets moved and invalidated with a Status-
323  // specific error message above. To aid debugging, set the status to a
324  // StatusOr-specific error message.
325  other.variant_.status_ =
326  Status(error::StatusError::MOVED, kStatusMoveConstructorMsg);
327 #endif
328  }
329  }
330 
331  /// Templatized constructor which constructs a `StatusOr<T>` by moving the
332  /// contents of an `absl::StatusOr<U>`. `T` must be implicitly constructible
333  /// from `U &&`.
334  ///
335  /// \param other The `absl::StatusOr<U>` object to move from.
336  template <typename U, typename E = typename std::enable_if<
337  is_implicitly_constructible<T, U &&>::value>::type>
338  StatusOr(absl::StatusOr<U> &&other) : has_value_(other.ok()) {
339  if (has_value_) {
340  new (&variant_) variant(*std::move(other));
341  } else {
342  new (&variant_) variant(std::move(other).status());
343  }
344  }
345 
346  /// Move-assignment operator.
347  ///
348  /// Sets `other` to a valid but unspecified state.
349  ///
350  /// \param other The StatusOr object to assign from.
351  StatusOr &operator=(StatusOr &&other) {
352  // Check for self-assignment.
353  if (this == &other) {
354  return *this;
355  }
356 
357  // Construct the variant object using the variant object of the donor.
358  if (other.has_value_) {
359  AssignValue(std::move(other.variant_.value_));
360  other.OverwriteValueWithStatus(
361  Status(error::StatusError::MOVED, kValueMoveAssignmentMsg));
362  } else {
363  AssignStatus(std::move(other.variant_.status_));
364 #ifndef NDEBUG
365  // The other.variant_.status_ gets moved and invalidated with a Status-
366  // specific error message above. To aid debugging, set the status to a
367  // StatusOr-specific error message.
368  other.variant_.status_ =
369  Status(error::StatusError::MOVED, kStatusMoveAssignmentMsg);
370 #endif
371  }
372 
373  return *this;
374  }
375 
376  // Implicit conversion operator to absl::StatusOr<U> for any type U that is
377  // implicitly constructible from T &&. This operator is provided for
378  // interoperability with Abseil status types.
379  template <typename U, typename E = typename std::enable_if<
380  is_implicitly_constructible<U, T &&>::value>::type>
381  operator absl::StatusOr<U>() const {
382  if (has_value_) {
383  return variant_.value_;
384  } else {
385  return variant_.status_;
386  }
387  }
388 
389  /// Indicates whether the object contains a `T` value.
390  ///
391  /// \return True if this StatusOr object's status is OK (i.e. a call to ok()
392  /// returns true). If this function returns true, then it is safe to
393  /// dereference this StatusOr.
394  bool ok() const { return has_value_; }
395 
396  /// Gets the stored status object, or an OK status if a `T` value is stored.
397  ///
398  /// \return The stored non-OK status object, or an OK status if this object
399  /// has a value.
400  Status status() const { return ok() ? OkStatus() : variant_.status_; }
401 
402  /// Gets the stored `T` value.
403  ///
404  /// If this StatusOr object is not OK, then this method either throws an
405  /// `absl::BadStatusOrAccess` exception or aborts the program, depending on
406  /// whether exceptions are enabled.
407  ///
408  /// \return The stored `T` value.
409  const T &value() const & {
410  if (!ok()) {
411  HandleBadValueCall();
412  }
413  return variant_.value_;
414  }
415 
416  /// Gets the stored `T` value.
417  ///
418  /// If this StatusOr object is not OK, then this method either throws an
419  /// `absl::BadStatusOrAccess` exception or aborts the program, depending on
420  /// whether exceptions are enabled.
421  ///
422  /// \return The stored `T` value.
423  T &value() & {
424  if (!ok()) {
425  HandleBadValueCall();
426  }
427  return variant_.value_;
428  }
429 
430  /// Moves and returns the internally-stored `T` value.
431  ///
432  /// The StatusOr object is invalidated after this call and will be updated to
433  /// a valid but unspecified state.
434  ///
435  /// If this StatusOr object is not OK, then this method either throws an
436  /// `absl::BadStatusOrAccess` exception or aborts the program, depending on
437  /// whether exceptions are enabled.
438  ///
439  /// \return The stored `T` value.
440  T value() && {
441  if (!ok()) {
442  HandleBadValueCall();
443  }
444  return std::move(*this).MoveValue();
445  }
446 
447  /// Gets the stored `T` value.
448  ///
449  /// This method should only be called if this StatusOr object's status is OK
450  /// (i.e. a call to ok() returns true), otherwise this call will abort.
451  ///
452  /// \deprecated Deprecated as part of Asylo's `absl::Status` migration. Use
453  /// `value()`, `operator*()`, or `operator->()` instead.
454  /// \return The stored `T` value.
455  ABSL_DEPRECATED(
456  "Deprecated as part of Asylo's absl::Status migration. Use value(), "
457  "operator*(), or operator->() instead.")
458  const T &ValueOrDie() const & { return **this; }
459 
460  /// Gets a mutable reference to the stored `T` value.
461  ///
462  /// This method should only be called if this StatusOr object's status is OK
463  /// (i.e. a call to ok() returns true), otherwise this call will abort.
464  ///
465  /// \deprecated Deprecated as part of Asylo's `absl::Status` migration. Use
466  /// `value()`, `operator*()`, or `operator->()` instead.
467  /// \return The stored `T` value.
468  ABSL_DEPRECATED(
469  "Deprecated as part of Asylo's absl::Status migration. Use value(), "
470  "operator*(), or operator->() instead.")
471  T &ValueOrDie() & { return **this; }
472 
473  /// Moves and returns the internally-stored `T` value.
474  ///
475  /// This method should only be called if this StatusOr object's status is OK
476  /// (i.e. a call to ok() returns true), otherwise this call will abort. The
477  /// StatusOr object is changed after this call to a valid but unspecified
478  /// state.
479  ///
480  /// \deprecated Deprecated as part of Asylo's `absl::Status` migration. Use
481  /// `value()`, `operator*()`, or `operator->()` instead.
482  /// \return The stored `T` value.
483  ABSL_DEPRECATED(
484  "Deprecated as part of Asylo's absl::Status migration. Use value(), "
485  "operator*(), or operator->() instead.")
486  T ValueOrDie() && { return *std::move(*this); }
487 
488  /// Gets the stored `T` value.
489  ///
490  /// This method should only be called if this StatusOr object's status is OK
491  /// (i.e. a call to ok() returns true), otherwise the behavior of this method
492  /// is undefined.
493  ///
494  /// \return The stored `T` value.
495  const T &operator*() const & {
496  if (!ok()) {
497  DieOnBadAccess();
498  }
499  return variant_.value_;
500  }
501 
502  /// Gets the stored `T` value.
503  ///
504  /// This method should only be called if this StatusOr object's status is OK
505  /// (i.e. a call to ok() returns true), otherwise the behavior of this method
506  /// is undefined.
507  ///
508  /// \return The stored `T` value.
509  T &operator*() & {
510  if (!ok()) {
511  DieOnBadAccess();
512  }
513  return variant_.value_;
514  }
515 
516  /// Gets the stored `T` value.
517  ///
518  /// This method should only be called if this StatusOr object's status is OK
519  /// (i.e. a call to ok() returns true), otherwise the behavior of this method
520  /// is undefined. The StatusOr object is changed after this call to a valid
521  /// but unspecified state.
522  ///
523  /// \return The stored `T` value.
524  T operator*() && {
525  if (!ok()) {
526  DieOnBadAccess();
527  }
528  return std::move(*this).MoveValue();
529  }
530 
531  /// Aecceses the stored `T` value.
532  ///
533  /// This method should only be called if this StatusOr object's status is OK
534  /// (i.e. a call to ok() returns true), otherwise the behavior of this method
535  /// is undefined.
536  ///
537  /// \return A pointer to the stored `T` value.
538  const T *operator->() const {
539  if (!ok()) {
540  DieOnBadAccess();
541  }
542  return &variant_.value_;
543  }
544 
545  /// Gets the stored `T` value.
546  ///
547  /// This method should only be called if this StatusOr object's status is OK
548  /// (i.e. a call to ok() returns true), otherwise the behavior of this method
549  /// is undefined.
550  ///
551  /// \return The stored `T` value.
552  T *operator->() {
553  if (!ok()) {
554  DieOnBadAccess();
555  }
556  return &variant_.value_;
557  }
558 
559  private:
560  // Resets the |variant_| member to contain |status|.
561  template <class U>
562  void AssignStatus(U &&status) {
563  if (ok()) {
564  OverwriteValueWithStatus(std::forward<U>(status));
565  } else {
566  // Reuse the existing Status object. has_value_ is already false.
567  variant_.status_ = std::forward<U>(status);
568  }
569  }
570 
571  // Under the assumption that |this| is currently holding a value, resets the
572  // |variant_| member to contain |status| and sets |has_value_| to indicate
573  // that |this| does not have a value. Destroys the existing |variant_| member.
574  template <class U>
575  void OverwriteValueWithStatus(U &&status) {
576 #ifndef NDEBUG
577  if (!ok()) {
578  LOG(FATAL) << "Object does not have a value to change from";
579  }
580 #endif
581  variant_.value_.~T();
582  new (&variant_) variant(std::forward<U>(status));
583  has_value_ = false;
584  }
585 
586  // Resets the |variant_| member to contain the |value| and sets |has_value_|
587  // to indicate that the StatusOr object has a value. Destroys the existing
588  // |variant_| member.
589  template <class U>
590  void AssignValue(U &&value) {
591  if (ok()) {
592  // We cannot assume that T is move-assignable.
593  variant_.value_.~T();
594  } else {
595  variant_.status_.~Status();
596  }
597  new (&variant_) variant(std::forward<U>(value));
598  has_value_ = true;
599  }
600 
601  // If exceptions are enabled, throw an absl::BadStatusOrAccess. Otherwise,
602  // crash the program.
603  //
604  // Requires this object to hold a Status.
605  void HandleBadValueCall() const {
606 #ifdef ABSL_HAVE_EXCEPTIONS
607  throw absl::BadStatusOrAccess(status());
608 #else
609  DieOnBadAccess();
610 #endif
611  }
612 
613  // If exceptions are enabled, throw an absl::BadStatusOrAccess. Otherwise,
614  // crash the program.
615  //
616  // Requires this object to hold a Status.
617  void DieOnBadAccess() const {
618  LOG(FATAL)
619  << "Object does not have a usable value, instead contains status: "
620  << status();
621  }
622 
623  // Moves the value out from this object. Requires this object to hold a value.
624  T MoveValue() && {
625  // Invalidate this StatusOr object before returning control to caller.
626  Cleanup set_moved_status([this] {
627  OverwriteValueWithStatus(
628  Status(error::StatusError::MOVED, kValueOrDieMovedMsg));
629  });
630  return std::move(variant_.value_);
631  }
632 
633  union variant {
634  // A non-OK status.
635  Status status_;
636 
637  // An element of type T.
638  T value_;
639 
640  variant() {}
641 
642  variant(const Status &status) : status_(status) {}
643 
644  variant(Status &&status) : status_(std::move(status)) {}
645 
646  template <typename U, typename E = typename std::enable_if<
647  is_implicitly_constructible<T, U>::value>::type>
648  variant(U &&value) : value_(std::forward<U>(value)) {}
649 
650  // This destructor must be explicitly defined because it is deleted due to
651  // the variant type having non-static data members with non-trivial
652  // destructors.
653  ~variant() {}
654  };
655 
656  // One of: a non-OK status or an element of type T.
657  variant variant_;
658 
659  // Indicates the active member of the variant_ member.
660  //
661  // A value of true indicates that value_ is the active member of variant_.
662  //
663  // A value of false indicates that status_ is the active member of variant_.
664  bool has_value_;
665 };
666 
667 } // namespace asylo
668 
669 #endif // ASYLO_UTIL_STATUSOR_H_
StatusOr()
Constructs a StatusOr object that contains a non-OK status.
Definition: statusor.h:156
StatusOr(const absl::Status &status)
Constructs a StatusOr object with the given non-OK absl::Status object.
Definition: statusor.h:196
ABSL_CONST_INIT const char kStatusMoveAssignmentMsg[]
~StatusOr()
Definition: statusor.h:160